/*
* Copyright 2015 LinkedIn Corp.
*
* 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 azkaban.executor.selector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.apache.log4j.Logger;
/** Implementation of the CandidateSelector.
* @param K executor object type.
* @param V dispatching object type.
* */
public class CandidateSelector<K extends Comparable<K>, V> implements Selector<K, V> {
private static Logger logger = Logger.getLogger(CandidateComparator.class);
private CandidateFilter<K,V> filter;
private CandidateComparator<K> comparator;
/**constructor of the class.
* @param filter CandidateFilter object to be used to perform the candidate filtering.
* @param comparator CandidateComparator object to be used to find the best suit candidate from the filtered list.
* */
public CandidateSelector(CandidateFilter<K,V> filter,
CandidateComparator<K> comparator){
this.filter = filter;
this.comparator = comparator;
}
@Override
public K getBest(Collection<K> candidateList, V dispatchingObject) {
// shortcut if the candidateList is empty.
if ( null == candidateList || candidateList.size() == 0){
logger.error("failed to getNext candidate as the passed candidateList is null or empty.");
return null;
}
logger.debug("start candidate selection logic.");
logger.debug(String.format("candidate count before filtering: %s", candidateList.size()));
// to keep the input untouched, we will form up a new list based off the filtering result.
Collection<K> filteredList = new ArrayList<K>();
if (null != this.filter){
for (K candidateInfo : candidateList){
if (filter.filterTarget(candidateInfo,dispatchingObject)){
filteredList.add(candidateInfo);
}
}
} else{
filteredList = candidateList;
logger.debug("skipping the candidate filtering as the filter object is not specifed.");
}
logger.debug(String.format("candidate count after filtering: %s", filteredList.size()));
if (filteredList.size() == 0){
logger.debug("failed to select candidate as the filtered candidate list is empty.");
return null;
}
if (null == comparator){
logger.debug("candidate comparator is not specified, default hash code comparator class will be used.");
}
// final work - find the best candidate from the filtered list.
K executor = Collections.max(filteredList, comparator);
logger.debug(String.format("candidate selected %s",
null == executor ? "(null)" : executor.toString()));
return executor;
}
@Override
public String getName() {
return "CandidateSelector";
}
}