Package er.memoryadaptor

Source Code of er.memoryadaptor.ERJoinEntityStore

package er.memoryadaptor;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NoSuchElementException;

import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOJoin;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.eocontrol.EOFetchSpecification;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;

import er.memoryadaptor.EREntityStore.JoinEntityStore;

/**
* ERJoinEntityStore is a datastore implementation that provides a basic EREntityStore join implementation.
* This class is used by EREntityStoreFactory when resolving an EREntityStore for an entity that has flattened
* attributes but doesn't implement {@link EREntityStore.JoinEntityStore}
*
* @author q
*/
public class ERJoinEntityStore extends EREntityStore implements JoinEntityStore {
  private NSDictionary<EOEntity, EREntityStore> _stores;
  private EOEntity _entity;

  public ERJoinEntityStore(NSDictionary<EOEntity, EREntityStore> stores, EOEntity entity) {
    _stores = stores;
    _entity = entity;
  }

  @Override
  public NSMutableArray<NSMutableDictionary<String, Object>> fetch(NSArray<EOAttribute> attributesToFetch, EOFetchSpecification fetchSpecification,
      boolean shouldLock, EOEntity entity, ERMemoryAdaptorContext context) {
    EREntityStore store = joinedStore(attributesToFetch, fetchSpecification, entity);
    return store.fetch(attributesToFetch, fetchSpecification, shouldLock, entity, context);
  }

  private EREntityStore joinedStore(NSArray<EOAttribute> attributesToFetch, EOFetchSpecification fetchSpecification, EOEntity entity) {
    EREntityStore store = _stores.objectForKey(entity);
    for (EOAttribute attrib : attributesToFetch) {
      if (attrib.isFlattened()) {
        EOAttribute _attrib = entity._attributeForPath(attrib.definition());
        EORelationship _rel = entity._relationshipForPath(attrib.relationshipPath());
        store = join(_rel, store, _stores.objectForKey(_attrib.entity()));
      }
    }
    // We need to check the qualifier for _hiddenRelationships and include them if referenced
//    for (EORelationship rel : (NSArray<EORelationship>) entity._hiddenRelationships()) {
//      if (rel.isFlattened()) {
//        for (EORelationship compRel : (NSArray<EORelationship>) rel.componentRelationships()) {
//          store = join(compRel, store, _stores.objectForKey(compRel.destinationEntity()));
//        }
//      } else {
//        store = join(rel, store, _stores.objectForKey(rel.destinationEntity()));
//      }
//    }
    return store;
  }

  private EREntityStore join(EORelationship rel, EREntityStore store1, EREntityStore store2) {
    /* FIXME: Need to support outer joins too */
    if (rel.joinSemantic() == EORelationship.InnerJoin)
      return new InnerJoinEntityStore(rel, store1, store2);
    throw new UnsupportedOperationException("ERMemoryAdaptor does not support outer joins");
  }

  @Override
  public Iterator<NSMutableDictionary<String, Object>> iterator() {
    return joinedStore(_entity.attributesToFetch(), null, _entity).iterator();
  }

  @Override
  public void insertRow(NSDictionary<String, Object> row, EOEntity entity) {
    NSMutableDictionary<String, Object> newRow = new NSMutableDictionary<String, Object>();
    EOEntity target = entity;
    /* XXX: This assumes that EOF isn't going to try to insert into two different tables at once */
    for (Entry<String, Object> entry : row.entrySet()) {
      EOAttribute attrib = entity.anyAttributeNamed(entry.getKey());
      if (attrib.isFlattened()) {
        EOAttribute _attrib = entity._attributeForPath(attrib.definition());
        target = _attrib.entity();
        newRow.setObjectForKey(entry.getValue(), _attrib.name());
      } else {
        newRow.setObjectForKey(entry.getValue(), attrib.name());
      }
    }
    _stores.objectForKey(target).insertRow(newRow, target);
  }
 
  @Override
  public int nextSequence() {
    return _stores.objectForKey(_entity).nextSequence();
  }

  private class InnerJoinEntityStore extends EREntityStore {
    NSMutableDictionary<EOAttribute, EOAttribute> attributeMap = new NSMutableDictionary<EOAttribute, EOAttribute>();
    EREntityStore srcStore;
    EREntityStore destStore;
    EORelationship relationship;

    @SuppressWarnings("cast")
    public InnerJoinEntityStore(EORelationship rel, EREntityStore store1, EREntityStore store2) {
      srcStore = store1;
      destStore = store2;
      relationship = rel;
      for (EOJoin join : (NSArray<EOJoin>)rel.joins()) {
        attributeMap.setObjectForKey(join.destinationAttribute(), join.sourceAttribute());
      }
    }

    @Override
    public Iterator<NSMutableDictionary<String, Object>> iterator() {
      return new InnerJoinIterator();
    }

    class InnerJoinIterator implements Iterator<NSMutableDictionary<String, Object>> {
      private Iterator<NSMutableDictionary<String, Object>> srcIterator;
      private Iterator<NSMutableDictionary<String, Object>> destIterator;
      private NSMutableDictionary<String, Object> src;
      private NSMutableDictionary<String, Object> dst;
      private Boolean _hasNext = null;

      public InnerJoinIterator() {
        srcIterator = srcStore.iterator();
        destIterator = destStore.iterator();
        if (srcIterator.hasNext()) {
          src = srcIterator.next();
        }
      }

      public boolean hasNext() {
        if (_hasNext != null) {
          return _hasNext.booleanValue();
        }
        while (_hasNext == null) {
          if (destIterator.hasNext()) {
            dst = destIterator.next();
          } else {
            if (srcIterator.hasNext()) {
              src = srcIterator.next();
              destIterator = destStore.iterator();
              continue;
            }
            _hasNext = Boolean.FALSE;
            break;
          }
          if (src == null) {
            _hasNext = Boolean.FALSE;
            break;
          }
          for (Entry<EOAttribute, EOAttribute> entry : attributeMap.entrySet()) {
            String srcKey = entry.getKey().columnName();
            String dstKey = entry.getValue().columnName();
            Object srcValue = src.objectForKey(srcKey);
            Object dstValue = dst.objectForKey(dstKey);
            if (srcValue == dstValue || srcValue != null && srcValue.equals(dstValue)) {
              _hasNext = Boolean.TRUE;
              break;
            }
          }
        }
        return _hasNext.booleanValue();
      }

      @SuppressWarnings("cast")
      public NSMutableDictionary<String, Object> next() {
        if (!hasNext()) {
          throw new NoSuchElementException("No more rows are available");
        }
        _hasNext = null;
        NSMutableDictionary<String, Object> row = new NSMutableDictionary<String, Object>(src);
        EOEntity entity = relationship.entity();
        for (EOAttribute attrib : (NSArray<EOAttribute>) entity.attributesToFetch()) {
          EORelationship rel = entity._relationshipForPath(attrib.relationshipPath());
          if (attrib.isFlattened() && relationship.equals(rel)) {
            String dstKey = entity._attributeForPath(attrib.definition()).columnName();
            Object value = dst.objectForKey(dstKey);
            row.setObjectForKey(value != null ? value : NSKeyValueCoding.NullValue, attrib.definition());
          }
        }
        //row.takeValueForKeyPath(rowFromStoredValues(dst, relationship.entity()), relationship.name());
        return row;
      }

      public void remove() {
        srcIterator.remove();
        //XXX: This should probably invalidate the destIterator
      }
    }

    @Override
    protected void _insertRow(NSMutableDictionary<String, Object> row, EOEntity entity) {
      throw new UnsupportedOperationException("Inserting rows is not supported in " + getClass().getName());
    }
  }

  @Override
  protected void _insertRow(NSMutableDictionary<String, Object> row, EOEntity entity) {
    throw new UnsupportedOperationException("Inserting rows is not supported in " + getClass().getName());
  }
}
TOP

Related Classes of er.memoryadaptor.ERJoinEntityStore

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.