All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.ethz.sn.visone3.io.impl.IdMapper Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of netroles.
 *
 * netroles is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * netroles is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with netroles.  If not, see .
 */

package ch.ethz.sn.visone3.io.impl;

import ch.ethz.sn.visone3.lang.ConstMapping;
import ch.ethz.sn.visone3.lang.Mapping;

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

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
 * Helper class to hold id mappings.
 */
public class IdMapper {
  private static final Logger LOG = LoggerFactory.getLogger(IdMapper.class);
  private final Map ids;
  private final Function generator;
  private final Class componentType;
  int generated = 0;

  /**
   * Returns a mapper constructed from the index -> id relationship specified
   * by the provided mapping.
   * 
   * @param ids the underlying mapping.
   * @param  the id type.
   * @return the id mapper.
   */
  public static  IdMapper fixed(final ConstMapping ids) {
    return fixed(ids.getComponentType(), inverseMap(ids));
  }

  /**
   * Returns a mapper constructed from the index -> id relationship specified
   * by the provided map.
   * 
   * @param   the id type.
   * @param type the class object describing the id type.
   * @param ids  the underlying map.
   * @return the id mapper.
   */
  public static  IdMapper fixed(Class type, final Map ids) {
    final int max = ids.values().stream().mapToInt(Integer::intValue).distinct().max().orElse(0);
    if (max >= ids.size()) {
      throw new IllegalArgumentException("maximum id exceeds size");
    }
    return new IdMapper<>(type, ids, (id) -> null);
  }

  /**
   * Returns a mapper representing the identity mapping index -> index.
   * @return the id mapper.
   */
  public static IdMapper identity() {
    return new IdMapper<>(Integer.class, new HashMap<>(), (id) -> id);
  }

  /**
   * Returns a mapper sequentially assigning new indices for new id values.
   * 
   * @param componentType the class object representing the id type.
   * @param            the id type.
   * @return the id mapper.
   */
  public static  IdMapper continous(final Class componentType) {
    final Map ids = new HashMap<>();
    return new IdMapper<>(componentType, ids, (id) -> ids.size());
  }

  private IdMapper(
    final Class componentType, final Map ids, final Function generator
  ) {
    this.componentType = componentType;
    this.ids = ids;
    this.generator = generator;
  }

  /**
   * Gets the type for ids.
   * @return the id type.
   */
  public Class getComponentType() {
    return componentType;
  }

  /**
   * Create the inverse mapping, warn if not ambiguous.
   *
   * @param source Integer to object mapping.
   * @return Object to integer mapping.
   */
  private static  Map inverseMap(final ConstMapping source) {
    final Map reverse = new HashMap<>();
    for (int i = 0; i < source.size(); i++) {
      final T key = source.get(i);
      if (!reverse.containsKey(key)) {
        reverse.put(key, i);
      } else {
        reverse.put(key, null);
        LOG.warn("ambiguous reverse mapping: '" + source.get(i) + "'");
      }
    }
    return reverse;
  }

  /**
   * Returns the number of assigned indices.
   * @return the number of assigned indices.
   */
  public int size() {
    return ids.size();
  }

  /**
   * Returns all id to index assignments.
   * @return set of all id to index assignments.
   */
  public Set> entrySet() {
    return ids.entrySet();
  }

  /**
   * Exports the gathered ids to a node mapping.
   *
   * @param offset  Where to start filling.
   * @param mapping Id map.
   */
  public void fillMapping(final int offset, final Mapping mapping) {
    for (final Map.Entry e : ids.entrySet()) {
      mapping.set(offset + e.getValue().intValue(), e.getKey());
    }
  }

  /**
   * Returns the map from ids to indices.
   * @return the map.
   */
  public Map getMapping() {
    return ids;
  }

  /**
   * Returns an index assigned to the specified id.
   * @param key the id.
   * @return the index assigned to this id.
   */
  public int map(final T key) {
    if (key == null) {
      // input is invalid
      return -1;
    }
    Integer id = ids.get(key);
    if (id == null) {
      // not present, try to generate
      id = generator.apply(key);
      if (id == null) {
        // generator returned null, cannot merge with existing
        return -1;
      }
      ids.put(key, id);
      generated++;
    }
    return id.intValue();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy