Package com.gentics.cr.util.indexing

Source Code of com.gentics.cr.util.indexing.AbstractUpdateCheckerJob

package com.gentics.cr.util.indexing;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.gentics.cr.CRConfig;
import com.gentics.cr.CRConfigUtil;
import com.gentics.cr.CRRequest;
import com.gentics.cr.CRResolvableBean;
import com.gentics.cr.RequestProcessor;
import com.gentics.cr.exceptions.CRException;
import com.gentics.cr.exceptions.WrongOrderException;
import com.gentics.cr.monitoring.MonitorFactory;
import com.gentics.cr.monitoring.UseCase;

/**
* This class is designed as an UpdateChecker for a ContentRepository. It checks
* a Gentics ContentRepository for Updates and gives updated Documents to some
* class
* @author perhab
*
*/
public abstract class AbstractUpdateCheckerJob implements Runnable {

  /**
   * Log4j logger for error and debug messages.
   */
  protected static Logger log = Logger.getLogger(AbstractUpdateCheckerJob.class);

  /**
   * Name of class to use for IndexLocation, must extend
   * {@link com.gentics.cr.util.indexing.IndexLocation}.
   */
  public static final String INDEXLOCATIONCLASS = "com.gentics.cr.util.indexing.IndexLocation";

  /**
   * Configuration key for the attribute containing the id.
   * @see #idAttribute
   */
  protected static final String ID_ATTRIBUTE_KEY = "IDATTRIBUTE";

  /**
   * Configuration key for the attribute containing an indicator if the object
   * was updated.
   * @see #timestampAttribute
   */
  private static final String TIMESTAMP_ATTR_KEY = "updateattribute";

  /**
   * Configuration of the UpdateCheckerJob.
   */
  protected CRConfig config;
  /**
   * Identifier of the UpdateCheckerJob.
   */
  protected String identifyer;
  /**
   * Status of the Indexer.
   */
  protected IndexerStatus status;

  /**
   * Name of the attribute identifying the beans.
   */
  protected String idAttribute = "contentid";

  /**
   * Name of the attribute indicating if the object has changed. This
   * attribute should change whenever the object is changed in the repository.
   */
  protected String timestampAttribute = "";

  private ConcurrentHashMap<String, CRConfigUtil> configmap;

  /**
   * index location to compare the objects with.
   */
  protected IndexLocation indexLocation;

  /**
   * marker for saving the duration in milliseconds.
   */
  private long duration = 0;

  /**
   * start time of the job as timestamp.
   */
  private long start = 0;

  /**
   * Initialises the default values for any implementation of the
   * {@link AbstractUpdateCheckerJob}.
   * @param updateCheckerConfig Configuration of the update job
   * @param indexLoc index location to compare with the repository
   * @param updateCheckerConfigmap TODO javadoc
   */
  public AbstractUpdateCheckerJob(final CRConfig updateCheckerConfig, final IndexLocation indexLoc,
    final ConcurrentHashMap<String, CRConfigUtil> updateCheckerConfigmap) {
    config = updateCheckerConfig;
    configmap = updateCheckerConfigmap;
    if (configmap == null) {
      log.debug("Configmap is empty");
    }
    identifyer = (String) updateCheckerConfig.getName();
    indexLocation = indexLoc;
    status = new IndexerStatus();
    idAttribute = updateCheckerConfig.getString(ID_ATTRIBUTE_KEY, idAttribute);
    timestampAttribute = updateCheckerConfig.getString(TIMESTAMP_ATTR_KEY, timestampAttribute);
  }

  /**
   * Gets the config for this UpdateCheckerJob.
   *
   * @return configuration as CRConfig-object
   */
  public final CRConfig getConfig() {
    return config;
  }

  /**
   * Gets the Job Identifyer. In most cases this is the CR id.
   * @return identifyer as string
   */
  public final String getIdentifyer() {
    return identifyer;
  }

  /**
   * Get job duration in milliseconds.
   * @return duration of the job in milliseconds
   */
  public final long getDuration() {
    return duration;
  }

  /**
   * Get the job's start time as timestamp.
   * @return start time of the job as timestamp
   */
  public final long getStart() {
    return this.start;
  }

  /**
   * Get the job's start time as date.
   * @return start time of the job as date
   */
  public final Date getStartDate() {
    return new Date(getStart());
  }

  /**
   * Get total count of objects to index.
   * @return object count as int.
   */
  public final int getObjectsToIndex() {
    return status.getObjectCount();
  }

  /**
   * Get the number ob objects already indexed.
   * @return objects already indexed in the current job
   */
  public final int getObjectsDone() {
    return status.getObjectsDone();
  }

  /**
   * Calculates ETA of the current job.
   * @return ETA in ms
   */
  public final long getETA() {
    long eta = 0;

    long objDone = this.getObjectsDone();
    long objToIndex = this.getObjectsToIndex();
    long objTodo = objToIndex - objDone;

    long timetaken = System.currentTimeMillis() - this.getStart();

    long timePerObj = 0;
    if (objDone != 0) {
      timePerObj = timetaken / objDone;
    }

    eta = objTodo * timePerObj;

    return eta;
  }

  /**
   * Get Current Status as String.
   * @return current status string
   */
  public final String getStatusString() {
    return status.getCurrentStatusString();
  }

  /**
   * Check if job had an error.
   * @return true if error.
   */
  public final boolean hasError() {
    return status.hasError();
  }

  /**
   * Get the current error message if set.
   * @return error message.
   */
  public final String getErrorMessage() {
    return status.getErrorMessage();
  }

  /**
   * Tests if a {@link AbstractUpdateCheckerJob} has the same identifier as
   * the given object being an instance of {@link AbstractUpdateCheckerJob}.
   * @param obj Object to test if it is equal to this
   * @return <code>true</code> if is equal to obj, otherwise false.
   */
  @Override
  public boolean equals(final Object obj) {
    if (obj instanceof AbstractUpdateCheckerJob) {
      if (this.identifyer.equalsIgnoreCase(((AbstractUpdateCheckerJob) obj).getIdentifyer())) {
        return true;
      }
    }
    return false;
  }
 
  @Override
  public int hashCode() {
    return this.identifyer.hashCode();
  }

  /**
   * get the objects to update and update them in the index.
   * @param indexLocation - index location to update
   * @param config - configuration of the update job
   * @throws CRException in case something goes wrong please document in your implementation if you plan to throw an exception
   */
  protected abstract void indexCR(IndexLocation indexLocation, CRConfigUtil config) throws CRException;

  /**
   * get all objects that are not up to date.
   * @param forceFullUpdate - boolean use to force a full update in the index
   * @param request - Request describing the objects to index.
   * @param rp - RequestProcessor to get the objects from.
   * @param indexUpdateChecker - update checker for the index.
   * @return {@link Collection} of {@link CRResolvableBean} that need to be
   * updated in the index.
   * @see IndexUpdateChecker#isUpToDate(String, Object, String,
   * com.gentics.api.lib.resolving.Resolvable)
   * @see IndexUpdateChecker#deleteStaleObjects()
   */
  protected Collection<CRResolvableBean> getObjectsToUpdate(final CRRequest request, final RequestProcessor rp,
      final boolean forceFullUpdate, final IndexUpdateChecker indexUpdateChecker) {
    Collection<CRResolvableBean> updateObjects = new Vector<CRResolvableBean>();

    UseCase objectsToUpdateCase = MonitorFactory.startUseCase("AbstractUpdateCheck.getObjectsToUpdate("
        + request.get("CRID") + ")");
    try {
      if (forceFullUpdate || "".equals(timestampAttribute)) {
        try {
          updateObjects = (Collection<CRResolvableBean>) rp.getObjects(request);
        } catch (CRException e) {
          String message = "Error getting objects to full index from " + "RequestProcessor. "
              + e.getMessage();
          log.error(message, e);
          status.setError(message);
        }
      } else {
        //Sorted (by the idAttribute) list of Resolvables to check for
        //Updates.
        Collection<CRResolvableBean> objectsToIndex;
        try {
          defaultizeRequest(request);
          objectsToIndex = (Collection<CRResolvableBean>) rp.getObjects(request);
        } catch (CRException e) {
          String message = "Error getting objects to index from " + "RequestProcessor. " + e.getMessage();
          log.error(message, e);
          status.setError(message);
          return null;
        }
        Iterator<CRResolvableBean> resolvableIterator = objectsToIndex.iterator();
        try {
          while (resolvableIterator.hasNext()) {
            CRResolvableBean crElement = resolvableIterator.next();
            Object crElementIDObject = crElement.get(idAttribute);
            if (crElementIDObject == null) {
              log.error("IDAttribute is null!");
            }
            String crElementID = crElementIDObject.toString();
            Object crElementTimestamp = crElement.get(timestampAttribute);
            //TODO: if any transformers change an attribute that is used for the update check we have to run the transformers
            //before
            if (!indexUpdateChecker.isUpToDate(
              crElementID,
              crElementTimestamp,
              timestampAttribute,
              crElement)) {
              updateObjects.add(crElement);
            }
          }
        } catch (WrongOrderException e) {
          log.error("Got the objects from the datasource in the wrong" + "order.", e);
          status.setError("Got the objects from the datasource in the" + "wrong order.");
          return null;
        }
      }
      //Finally delete all Objects from Index that are not checked for an
      //Update
      //fixing possible npe
      if (indexUpdateChecker != null) {
        indexUpdateChecker.deleteStaleObjects();
      }
    } finally {
      objectsToUpdateCase.stop();
    }
    return updateObjects;
  }

  private void defaultizeRequest(CRRequest request) {
    String[] prefill = request.getAttributeArray(idAttribute);
    List<String> prefillList = Arrays.asList(prefill);
    if (!"".equals(timestampAttribute) && !prefillList.contains(timestampAttribute)) {
      ArrayList<String> pf = new ArrayList<String>(prefillList);
      pf.add(timestampAttribute);
      request.setAttributeArray(pf.toArray(prefill));
    }
    String[] sorting = request.getSortArray();
    if (sorting == null) {
      request.setSortArray(new String[] { idAttribute + ":asc" });
    } else if (!Arrays.asList(sorting).contains(idAttribute + ":asc")) {
      ArrayList<String> sf = new ArrayList<String>(Arrays.asList(sorting));
      sf.add(idAttribute + ":asc");
      request.setSortArray(sf.toArray(sorting));
    }
  }

  /**
   * Executes the index process.
   */
  public void run() {
    this.start = System.currentTimeMillis();
    try {
      indexCR(this.indexLocation, (CRConfigUtil) this.config);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
    this.duration = System.currentTimeMillis() - start;
  }

}
TOP

Related Classes of com.gentics.cr.util.indexing.AbstractUpdateCheckerJob

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.