/**
   * Counts all entities of the specified type matching the given {@link Query} instance. The SQL
   * runs as a <code>SELECT COUNT(*)</code> to ensure maximum performance.
   *
   * @param type The type of the entities which should be counted.
   * @param query The {@link Query} instance used to determine the result set which will be counted.
   * @return The number of entities of the given type which match the specified query.
   */
  public <K> int count(Class<? extends RawEntity<K>> type, Query query) throws SQLException {
    int back = -1;

    Connection conn = getProvider().getConnection();
    try {
      String sql = null;
      tableNameConverterLock.readLock().lock();
      try {
        sql = query.toSQL(type, provider, tableNameConverter, getFieldNameConverter(), true);
      } finally {
        tableNameConverterLock.readLock().unlock();
      }

      Logger.getLogger("net.java.ao").log(Level.INFO, sql);
      PreparedStatement stmt = conn.prepareStatement(sql);
      provider.setQueryStatementProperties(stmt, query);

      query.setParameters(this, stmt);

      ResultSet res = stmt.executeQuery();
      if (res.next()) {
        back = res.getInt(1);
      }
      res.close();
      stmt.close();
    } finally {
      conn.close();
    }

    return back;
  }
 public boolean checkIfFavorite(String listingID) {
   String queryf =
       "select * from "
           + FavoriteParkingSchema.TABLE_NAME
           + " where "
           + FavoriteParkingSchema.LISTING_ID
           + "='"
           + listingID
           + "'";
   return mProvider.itemExists(queryf);
 }
 public void addFavorite(GarageModel garageModel) {
   if (!Utils.isStringEmpty(garageModel.getListingID())) {
     FavoriteParking favorite = new FavoriteParking();
     favorite.listingID = garageModel.getListingID();
     favorite.listingName = garageModel.getName();
     favorite.listingAddress = garageModel.getAddress();
     favorite.listingCity = garageModel.getCity();
     favorite.listingState = garageModel.getState();
     favorite.listingZip = garageModel.getZip();
     favorite.latitude = Double.toString(garageModel.getLatitude());
     favorite.longitude = Double.toString(garageModel.getLongitude());
     favorite.price = Integer.toString(garageModel.getPrice());
     mProvider.create(favorite);
   }
 }
 public ArrayList<GarageModel> getAllFavorites() {
   try {
     List<FavoriteParking> favoriteList = mProvider.getAll(FavoriteParking.class);
     if (!Utils.checkIfNull(favoriteList)) {
       ArrayList<GarageModel> garageModels = new ArrayList<>();
       for (FavoriteParking fp : favoriteList) {
         garageModels.add(favToPlace(fp));
       }
       return garageModels;
     }
   } catch (InstantiationException e) {
     e.printStackTrace();
   } catch (IllegalAccessException e) {
     e.printStackTrace();
   }
   return null;
 }
  /**
   * Selects all entities of the specified type which match the given <code>Query</code>. This
   * method creates a <code>PreparedStatement</code> using the <code>Query</code> instance specified
   * against the table represented by the given type. This query is then executed (with the
   * parameters specified in the query). The method then iterates through the result set and
   * extracts the specified field, mapping an entity of the given type to each row. This array of
   * entities is returned.
   *
   * @param type The type of the entities to retrieve.
   * @param field The field value to use in the creation of the entities. This is usually the
   *     primary key field of the corresponding table.
   * @param query The {@link Query} instance to use in determining the results.
   * @return An array of entities of the given type which match the specified query.
   */
  public <T extends RawEntity<K>, K> T[] find(Class<T> type, String field, Query query)
      throws SQLException {
    List<T> back = new ArrayList<T>();

    query.resolveFields(type, getFieldNameConverter());

    // <ian>
    Version version = type.getAnnotation(Version.class);
    if (version != null && !version.findInitial()) {
      // Add initial version check to exclude
      // objects that have only been created and not saved yet.
      if (query.getWhereClause() == null) {
        query.where(version.value() + " != ?", version.initial());
      } else {
        // Preserve existing WHERE clause and parameters
        String whereClause =
            new StringBuilder()
                .append(query.getWhereClause())
                .append(" AND ")
                .append(version.value())
                .append(" != ?")
                .toString();
        Object[] paramsOld = query.getWhereParams();
        Object[] paramsNew = new Object[paramsOld.length + 1];
        System.arraycopy(paramsOld, 0, paramsNew, 0, paramsOld.length);
        paramsNew[paramsNew.length - 1] = version.initial();
        query.setWhereClause(whereClause);
        query.setWhereParams(paramsNew);
      }
    }
    // </ian>

    Preload preloadAnnotation = type.getAnnotation(Preload.class);
    if (preloadAnnotation != null) {
      if (!query.getFields()[0].equals("*") && query.getJoins().isEmpty()) {
        String[] oldFields = query.getFields();
        List<String> newFields = new ArrayList<String>();

        for (String newField : preloadAnnotation.value()) {
          newField = newField.trim();

          int fieldLoc = -1;
          for (int i = 0; i < oldFields.length; i++) {
            if (oldFields[i].equals(newField)) {
              fieldLoc = i;
              break;
            }
          }

          if (fieldLoc < 0) {
            newFields.add(newField);
          } else {
            newFields.add(oldFields[fieldLoc]);
          }
        }

        if (!newFields.contains("*")) {
          for (String oldField : oldFields) {
            if (!newFields.contains(oldField)) {
              newFields.add(oldField);
            }
          }
        }

        query.setFields(newFields.toArray(new String[newFields.size()]));
      }
    }

    Connection conn = getProvider().getConnection();
    try {
      String sql = null;
      tableNameConverterLock.readLock().lock();
      try {
        sql = query.toSQL(type, provider, tableNameConverter, getFieldNameConverter(), false);
      } finally {
        tableNameConverterLock.readLock().unlock();
      }

      Logger.getLogger("net.java.ao").log(Level.INFO, sql);
      PreparedStatement stmt =
          conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      provider.setQueryStatementProperties(stmt, query);

      query.setParameters(this, stmt);

      ResultSet res = stmt.executeQuery();
      provider.setQueryResultSetProperties(res, query);

      while (res.next()) {
        T entity =
            peer(
                type,
                Common.getPrimaryKeyType(type)
                    .pullFromDatabase(this, res, Common.getPrimaryKeyClassType(type), field));
        CacheLayer cacheLayer = getProxyForEntity(entity).getCacheLayer(entity);

        for (String cacheField : query.getCanonicalFields(type, fieldNameConverter)) {
          cacheLayer.put(cacheField, res.getObject(cacheField));
        }

        back.add(entity);
      }
      res.close();
      stmt.close();
    } finally {
      conn.close();
    }

    return back.toArray((T[]) Array.newInstance(type, back.size()));
  }
  /**
   * Deletes the specified entities from the database. DELETE statements are called on the rows in
   * the corresponding tables and the entities are removed from the instance cache. The entity
   * instances themselves are not invalidated, but it doesn't even make sense to continue using the
   * instance without a row with which it is paired.
   *
   * <p>This method does attempt to group the DELETE statements on a per-type basis. Thus, if you
   * pass 5 instances of <code>EntityA</code> and two instances of <code>EntityB</code>, the
   * following SQL prepared statements will be invoked:
   *
   * <pre>DELETE FROM entityA WHERE id IN (?,?,?,?,?);
   * DELETE FROM entityB WHERE id IN (?,?);</pre>
   *
   * <p>Thus, this method scales very well for large numbers of entities grouped into types.
   * However, the execution time increases linearly for each entity of unique type.
   *
   * @param entities A varargs array of entities to delete. Method returns immediately if length ==
   *     0.
   */
  @SuppressWarnings("unchecked")
  public void delete(RawEntity<?>... entities) throws SQLException {
    if (entities.length == 0) {
      return;
    }

    Map<Class<? extends RawEntity<?>>, List<RawEntity<?>>> organizedEntities =
        new HashMap<Class<? extends RawEntity<?>>, List<RawEntity<?>>>();

    for (RawEntity<?> entity : entities) {
      verify(entity);
      Class<? extends RawEntity<?>> type = getProxyForEntity(entity).getType();

      if (!organizedEntities.containsKey(type)) {
        organizedEntities.put(type, new LinkedList<RawEntity<?>>());
      }
      organizedEntities.get(type).add(entity);
    }

    entityCacheLock.writeLock().lock();
    try {
      DatabaseProvider provider = getProvider();
      Connection conn = provider.getConnection();
      try {
        for (Class<? extends RawEntity<?>> type : organizedEntities.keySet()) {
          List<RawEntity<?>> entityList = organizedEntities.get(type);

          StringBuilder sql = new StringBuilder("DELETE FROM ");

          tableNameConverterLock.readLock().lock();
          try {
            sql.append(provider.processID(tableNameConverter.getName(type)));
          } finally {
            tableNameConverterLock.readLock().unlock();
          }

          sql.append(" WHERE ")
              .append(provider.processID(Common.getPrimaryKeyField(type, getFieldNameConverter())))
              .append(" IN (?");

          for (int i = 1; i < entityList.size(); i++) {
            sql.append(",?");
          }
          sql.append(')');

          Logger.getLogger("net.java.ao").log(Level.INFO, sql.toString());
          PreparedStatement stmt = conn.prepareStatement(sql.toString());

          int index = 1;
          for (RawEntity<?> entity : entityList) {
            TypeManager.getInstance()
                .getType((Class) entity.getEntityType())
                .putToDatabase(this, stmt, index++, entity);
          }

          relationsCache.remove(type);
          stmt.executeUpdate();
          stmt.close();
        }
      } finally {
        conn.close();
      }

      for (RawEntity<?> entity : entities) {
        entityCache.remove(new CacheKey(Common.getPrimaryKeyValue(entity), entity.getEntityType()));
      }

      proxyLock.writeLock().lock();
      try {
        for (RawEntity<?> entity : entities) {
          proxies.remove(entity);
        }
      } finally {
        proxyLock.writeLock().unlock();
      }
    } finally {
      entityCacheLock.writeLock().unlock();
    }
  }
  /**
   * Creates a new entity of the specified type with the optionally specified initial parameters.
   * This method actually inserts a row into the table represented by the entity type and returns
   * the entity instance which corresponds to that row.
   *
   * <p>The {@link DBParam} object parameters are designed to allow the creation of entities which
   * have non-null fields which have no defalut or auto-generated value. Insertion of a row without
   * such field values would of course fail, thus the need for db params. The db params can also be
   * used to set the values for any field in the row, leading to more compact code under certain
   * circumstances.
   *
   * <p>Unless within a transaction, this method will commit to the database immediately and exactly
   * once per call. Thus, care should be taken in the creation of large numbers of entities. There
   * doesn't seem to be a more efficient way to create large numbers of entities, however one should
   * still be aware of the performance implications.
   *
   * <p>This method delegates the action INSERT action to {@link
   * DatabaseProvider#insertReturningKey(EntityManager, Connection, Class, String, boolean, String,
   * DBParam...)}. This is necessary because not all databases support the JDBC <code>
   * RETURN_GENERATED_KEYS</code> constant (e.g. PostgreSQL and HSQLDB). Thus, the database provider
   * itself is responsible for handling INSERTion and retrieval of the correct primary key value.
   *
   * @param type The type of the entity to INSERT.
   * @param params An optional varargs array of initial values for the fields in the row. These
   *     values will be passed to the database within the INSERT statement.
   * @return The new entity instance corresponding to the INSERTed row.
   * @see net.java.ao.DBParam
   * @see net.java.ao.DatabaseProvider#insertReturningKey(EntityManager, Connection, Class, String,
   *     boolean, String, DBParam...)
   */
  public <T extends RawEntity<K>, K> T create(Class<T> type, DBParam... params)
      throws SQLException {
    T back = null;
    String table = null;

    tableNameConverterLock.readLock().lock();
    try {
      table = tableNameConverter.getName(type);
    } finally {
      tableNameConverterLock.readLock().unlock();
    }

    Set<DBParam> listParams = new HashSet<DBParam>();
    listParams.addAll(Arrays.asList(params));

    fieldNameConverterLock.readLock().lock();
    try {
      for (Method method : MethodFinder.getInstance().findAnnotation(Generator.class, type)) {
        Generator genAnno = method.getAnnotation(Generator.class);
        String field = fieldNameConverter.getName(method);
        ValueGenerator<?> generator;

        valGenCacheLock.writeLock().lock();
        try {
          if (valGenCache.containsKey(genAnno.value())) {
            generator = valGenCache.get(genAnno.value());
          } else {
            generator = genAnno.value().newInstance();
            valGenCache.put(genAnno.value(), generator);
          }
        } catch (InstantiationException e) {
          continue;
        } catch (IllegalAccessException e) {
          continue;
        } finally {
          valGenCacheLock.writeLock().unlock();
        }

        listParams.add(new DBParam(field, generator.generateValue(this)));
      }
      // <ian>
      Version version = type.getAnnotation(Version.class);
      if (version != null) {
        // Initialize version upon creation.
        String field = version.value();
        int initial = version.initial();
        listParams.add(new DBParam(field, initial));
      }
      // </ian>
    } finally {
      fieldNameConverterLock.readLock().unlock();
    }

    Connection conn = getProvider().getConnection();
    try {
      Method pkMethod = Common.getPrimaryKeyMethod(type);
      back =
          peer(
              type,
              provider.insertReturningKey(
                  this,
                  conn,
                  Common.getPrimaryKeyClassType(type),
                  Common.getPrimaryKeyField(type, getFieldNameConverter()),
                  pkMethod.getAnnotation(AutoIncrement.class) != null,
                  table,
                  listParams.toArray(new DBParam[listParams.size()])));
    } finally {
      conn.close();
    }

    relationsCache.remove(type);

    back.init();

    return back;
  }
 /**
  * Creates a new instance of <code>EntityManager</code> by auto-magically finding a {@link
  * DatabaseProvider} instance for the specified JDBC URI, username and password. The
  * auto-magically determined instance is pooled by default (if a supported connection pooling
  * library is available on the classpath).
  *
  * <p>The actual auto-magical parsing code isn't contained within this method, but in {@link
  * DatabaseProvider#getInstance(String, String, String)}. This way, it is possible to use the
  * parsing logic to get a <code>DatabaseProvider</code> instance separate from <code>EntityManager
  * </code> if necessary.
  *
  * @param uri The JDBC URI to use for the database connection.
  * @param username The username to use in authenticating the database connection.
  * @param password The password to use in authenticating the database connection.
  * @see #EntityManager(DatabaseProvider)
  * @see net.java.ao.DatabaseProvider#getInstance(String, String, String)
  */
 public EntityManager(String uri, String username, String password) {
   this(DatabaseProvider.getInstance(uri, username, password));
 }
 public void deleteAllFavorites() {
   mProvider.deleteAllData(FavoriteParkingSchema.TABLE_NAME);
 }
 public void deleteFavorite(GarageModel garageModel) {
   mProvider.delete(
       FavoriteParkingSchema.TABLE_NAME,
       FavoriteParkingSchema.LISTING_ID + " = ?",
       new String[] {garageModel.getListingID()});
 }
 public FavoriteParkingProvider(Context context) {
   mContext = context;
   mProvider = DatabaseProvider.getInstance(mContext);
 }