Package net.sf.collabreview.reputation

Source Code of net.sf.collabreview.reputation.MetricReviewAgedCount

/*
   Copyright 2012 Christian Prause and Fraunhofer FIT

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package net.sf.collabreview.reputation;

import net.sf.collabreview.core.Artifact;
import net.sf.collabreview.core.Repository;
import net.sf.collabreview.core.configuration.ConfigurationData;
import net.sf.collabreview.hooks.Hook;
import net.sf.collabreview.hooks.PostAddHook;
import net.sf.collabreview.hooks.PreAddHook;
import net.sf.collabreview.hooks.SetReviewHook;
import net.sf.collabreview.repository.Review;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
* Counts all of an author's reviews, but a review is only worth its timeliness.
* The metric will update its scores automatically if a review is updated or if a new artifact is added.
* It does not need to do a complete recalculation.
*
* @author Christian Prause (chris)
* @date 2010-08-08 15:52:16
*/
public class MetricReviewAgedCount extends ReputationMetric {
  /**
   * Buffer for preparing the new data when an update is in progress.
   */
  private Map<String, Float> newData;

  /**
   * The Hooks that this ReputationMetric has registered.
   */
  private List<Hook> registeredHooks = new LinkedList<Hook>();

  @Override
  protected void configure(ConfigurationData configuration) {
    SetReviewHook setReviewHook = new SetReviewHook() {
      @Override
      public int getPriority() {
        return PRIORITY_MEDIUM;
      }

      @Override
      public synchronized void reviewUpdated(Repository repository, Review oldReview, Review newReview) {
        assert repository == MetricReviewAgedCount.this.getRepository();
        MetricReviewAgedCount.this.reviewUpdated(repository, oldReview, newReview);
      }
    };
    PreAddHook preAddHook = new PreAddHook() {
      @Override
      public int getPriority() {
        return PRIORITY_MEDIUM;
      }

      @Override
      public synchronized void addingArtifact(Repository repository, Artifact newArtifact) {
        assert repository == MetricReviewAgedCount.this.getRepository();
        MetricReviewAgedCount.this.decrementCountersForArtifact(newArtifact);
      }
    };
    PostAddHook postAddHook = new PostAddHook() {
      @Override
      public int getPriority() {
        return PRIORITY_MEDIUM;
      }

      @Override
      public synchronized void artifactAdded(Repository repository, Artifact artifact) {
        assert repository == MetricReviewAgedCount.this.getRepository();
        MetricReviewAgedCount.this.incrementCountersForArtifact(artifact);
        setScores();
      }
    };
    // configure update hooks
    getRepository().registerSetReviewHook(setReviewHook);
    getRepository().registerPreAddHook(preAddHook);
    getRepository().registerPostAddHook(postAddHook);
    // remember for later removal when metric is destroyed
    registeredHooks.add(setReviewHook);
    registeredHooks.add(preAddHook);
    registeredHooks.add(postAddHook);
  }

  @Override
  protected void destroy() {
    for (Hook hook : registeredHooks) {
      getRepository().removeHook(hook);
    }
  }

  @Override
  protected void beginVisiting() {
    newData = new HashMap<String, Float>();
  }

  @Override
  protected void visit(Artifact artifact) {
    incrementCountersForArtifact(artifact);
  }

  @Override
  protected Map<String, Float> endVisiting() {
    return newData;
  }

  @Override
  public String getDefaultName() {
    return "agedcount";
  }

  /**
   * Handle update of a review.
   *
   * @param repository the Repository to use for loading artifacts
   * @param oldReview  the review that is being replaced
   * @param newReview  the review that replaces the old review
   */
  private void reviewUpdated(Repository repository, Review oldReview, Review newReview) {
    if (getFilter() != null && !getFilter().filter(newReview.getArtifactIdentifier(), repository)) {
      return;
    }
    if (newData == null || isUpdateInProgress()) {
      setUpToDate(false);
      return;
    }
    String reviewerName = newReview.getAuthor().getName();
    Float agedCount = newData.get(reviewerName);
    if (oldReview != null) {
      agedCount -= getReviewWeight(oldReview);
    } else if (agedCount == null) {
      // The user has added a new review, which means that he possibly does not have a score yet if this is his very first review.
      // In this case we must start a new counter.
      agedCount = 0f;
    }
    agedCount += getReviewWeight(newReview);
    newData.put(reviewerName, agedCount);
    setScores();
  }

  /**
   * What is the weight of the Review?
   * The value is the review Timeliness in this ReputationMetric but the method is provided for overloading by other metrics.
   *
   * @param review the review to be measured by this method
   * @return the Review's weight
   */
  protected float getReviewWeight(Review review) {
    return review.getTimeliness();
  }

  /**
   * Update the metric's cached scores with newData.
   */
  private void setScores() {
    setAuthorScores(new HashMap<String, Float>(newData));
  }

  /**
   * Part of the update process when a new artifact revision is added to the repository; increments the reputation counters with the reviews' new timelinesses.
   * Invocation of this method is typically preceeded by an invocation of decrementCountersForArtifact(), or is part of a re-calculation process.
   *
   * @param artifact the artifact that has a new revision
   * @see net.sf.collabreview.reputation.MetricReviewAgedCount#decrementCountersForArtifact(net.sf.collabreview.core.Artifact)
   */
  private void incrementCountersForArtifact(Artifact artifact) {
    manipulateCounterForArtifact(artifact, +1);
  }

  /**
   * Part of the update process when a new artifact revision is added to the repository; decrements the reputation counters with the reviews' old timelinesses.
   * It is typically followed by an incrementCountersForArtifact().
   *
   * @param artifact the artifact that has a new revision
   * @see net.sf.collabreview.reputation.MetricReviewAgedCount#incrementCountersForArtifact(net.sf.collabreview.core.Artifact)
   */
  private void decrementCountersForArtifact(Artifact artifact) {
    manipulateCounterForArtifact(artifact, -1);
  }

  /**
   * Increments or decrements the user's reputation scores based on his review's timeliness for a certain artifact.
   *
   * @param artifact  the artifact that is being updated
   * @param increment +1 if a counters should be incremented, and -1 if they should be decremented
   */
  private void manipulateCounterForArtifact(Artifact artifact, int increment) {
    if (getFilter() != null && !getFilter().filter(artifact)) {
      return;
    }
    for (Review review : getRepository().listReviews(artifact.getId().getName(), artifact.getId().getBranch())) {
      String reviewerName = review.getAuthor().getName();
      Float oldValue = newData.get(reviewerName);
      if (oldValue == null) {
        newData.put(reviewerName, getReviewWeight(review) * increment);
      } else {
        newData.put(reviewerName, oldValue + (getReviewWeight(review) * increment));
      }
    }
  }
TOP

Related Classes of net.sf.collabreview.reputation.MetricReviewAgedCount

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.