<commit_before>package brooklyn.event.basic;

import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import brooklyn.config.ConfigKey;
import brooklyn.entity.Entity;
import brooklyn.event.Sensor;
import brooklyn.location.Location;
import brooklyn.location.MachineLocation;
import brooklyn.location.PortRange;
import brooklyn.location.PortSupplier;
import brooklyn.location.basic.Locations;
import brooklyn.util.flags.TypeCoercions;

import com.google.common.base.Optional;
import com.google.common.collect.Iterables;

/**
 * A {@link Sensor} describing a port on a system,
 * with a {@link ConfigKey} which can be configured with a port range
 * (either a number e.g. 80, or a string e.g. "80" or "8080-8089" or even "80, 8080-8089, 8800+", or a list of these).
 * <p>
 * To convert at runtime a single port is chosen, respecting the entity.
 */
public class PortAttributeSensorAndConfigKey extends AttributeSensorAndConfigKey<PortRange,Integer> {
    private static final long serialVersionUID = 4680651022807491321L;
    
    public static final Logger LOG = LoggerFactory.getLogger(PortAttributeSensorAndConfigKey.class);

    public PortAttributeSensorAndConfigKey(String name) {
        this(name, name, null);
    }
    public PortAttributeSensorAndConfigKey(String name, String description) {
        this(name, description, null);
    }
    public PortAttributeSensorAndConfigKey(String name, String description, Object defaultValue) {
        super(PortRange.class, Integer.class, name, description, defaultValue);
    }
    public PortAttributeSensorAndConfigKey(PortAttributeSensorAndConfigKey orig, Object defaultValue) {
        super(orig, TypeCoercions.coerce(defaultValue, PortRange.class));
    }
    protected Integer convertConfigToSensor(PortRange value, Entity entity) {
        if (value==null) return null;
        Collection<? extends Location> locations = entity.getLocations();
        if (!locations.isEmpty()) {
            Optional<MachineLocation> lo = Locations.findUniqueMachineLocation(locations);
            if (lo.isPresent()) {
                Location l = lo.get();
                if (l instanceof PortSupplier) {
                    int p = ((PortSupplier)l).obtainPort(value);
                    if (p!=-1) {
                        LOG.debug(""+entity+" choosing port "+p+" for "+getName());
                        return p;
                    }
                    int rangeSize = Iterables.size(value);
                    if (rangeSize==0)
                        LOG.warn(""+entity+" no port available for "+getName()+" (empty range "+value+")");
                    else if (rangeSize==1) {
                        Integer pp = value.iterator().next();
                        if (pp>1024)
                            LOG.warn(""+entity+" port "+pp+" not available for "+getName());
                        else 
                            LOG.warn(""+entity+" port "+pp+" not available for "+getName()+" (root may be required?)");
                    } else {
                        LOG.warn(""+entity+" no port available for "+getName()+" (tried range "+value+")");
                    }
                    // definitively, no ports available
                    return null;
                }
                // ports may be available, we just can't tell from the location
                Integer v = (value.isEmpty() ? null : value.iterator().next());
                LOG.debug(""+entity+" choosing port "+v+" (unconfirmed) for "+getName());
                return v;
            } else {
                LOG.warn(""+entity+" ports not applicable, or not yet applicable, because has multiple locations "+locations+"; ignoring "+getName());       
            }
        } else {
            LOG.warn(""+entity+" ports not applicable, or not yet applicable, bacause has no locations, ignoring "+getName());<commit_msg>Make behaviour of PortAttributeSensorAndConfigKey.convertConfigToSensor backwards compatible<commit_after>package brooklyn.event.basic;

import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import brooklyn.config.ConfigKey;
import brooklyn.entity.Entity;
import brooklyn.event.Sensor;
import brooklyn.location.Location;
import brooklyn.location.MachineLocation;
import brooklyn.location.MachineProvisioningLocation;
import brooklyn.location.PortRange;
import brooklyn.location.PortSupplier;
import brooklyn.location.basic.Locations;
import brooklyn.util.flags.TypeCoercions;

import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;

/**
 * A {@link Sensor} describing a port on a system,
 * with a {@link ConfigKey} which can be configured with a port range
 * (either a number e.g. 80, or a string e.g. "80" or "8080-8089" or even "80, 8080-8089, 8800+", or a list of these).
 * <p>
 * To convert at runtime a single port is chosen, respecting the entity.
 */
public class PortAttributeSensorAndConfigKey extends AttributeSensorAndConfigKey<PortRange,Integer> {
    private static final long serialVersionUID = 4680651022807491321L;
    
    public static final Logger LOG = LoggerFactory.getLogger(PortAttributeSensorAndConfigKey.class);

    public PortAttributeSensorAndConfigKey(String name) {
        this(name, name, null);
    }
    public PortAttributeSensorAndConfigKey(String name, String description) {
        this(name, description, null);
    }
    public PortAttributeSensorAndConfigKey(String name, String description, Object defaultValue) {
        super(PortRange.class, Integer.class, name, description, defaultValue);
    }
    public PortAttributeSensorAndConfigKey(PortAttributeSensorAndConfigKey orig, Object defaultValue) {
        super(orig, TypeCoercions.coerce(defaultValue, PortRange.class));
    }
    protected Integer convertConfigToSensor(PortRange value, Entity entity) {
        if (value==null) return null;
        Collection<? extends Location> locations = entity.getLocations();
        if (!locations.isEmpty()) {
            Optional<? extends Location> lo = Locations.findUniqueMachineLocation(locations);
            if (!lo.isPresent()) {
                // Try a unique location which isn't a machine provisioner
                Iterator<? extends Location> li = Iterables.filter(locations,
                        Predicates.not(Predicates.instanceOf(MachineProvisioningLocation.class))).iterator();
                if (li.hasNext()) lo = Optional.of(li.next());
                if (li.hasNext()) lo = Optional.absent();
            }
            // Fall back to selecting the single location
            if (!lo.isPresent() && locations.size() == 1) {
                lo = Optional.of(locations.iterator().next());
            }
            if (LOG.isTraceEnabled()) {
                LOG.trace("Convert config to sensor for {} found locations: {}. Selected: {}",
                        new Object[] {entity, locations, lo});
            }
            if (lo.isPresent()) {
                Location l = lo.get();
                if (l instanceof PortSupplier) {
                    int p = ((PortSupplier)l).obtainPort(value);
                    if (p!=-1) {
                        LOG.debug(""+entity+" choosing port "+p+" for "+getName());
                        return p;
                    }
                    int rangeSize = Iterables.size(value);
                    if (rangeSize==0)
                        LOG.warn(""+entity+" no port available for "+getName()+" (empty range "+value+")");
                    else if (rangeSize==1) {
                        Integer pp = value.iterator().next();
                        if (pp>1024)
                            LOG.warn(""+entity+" port "+pp+" not available for "+getName());
                        else
                            LOG.warn(""+entity+" port "+pp+" not available for "+getName()+" (root may be required?)");
                    } else {
                        LOG.warn(""+entity+" no port available for "+getName()+" (tried range "+value+")");
                    }
                    // definitively, no ports available
                    return null;
                }
                // ports may be available, we just can't tell from the location
                Integer v = (value.isEmpty() ? null : value.iterator().next());
                LOG.debug(""+entity+" choosing port "+v+" (unconfirmed) for "+getName());
                return v;
            } else {
                LOG.warn(""+entity+" ports not applicable, or not yet applicable, because has multiple locations "+locations+"; ignoring "+getName());
            }
        } else {
            LOG.warn(""+entity+" ports not applicable, or not yet applicable, bacause has no locations, ignoring "+getName());
{'fraction_non_alphanumeric': 0.11131201265679738, 'fraction_numerical': 0.012317776019889252, 'mean_word_length': 2.33710407239819, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6891803', 'n_tokens_mistral': 2336, 'n_tokens_neox': 2210, 'n_words': 649}