001/* Copyright (C) 2013 TU Dortmund 002 * This file is part of AutomataLib, http://www.automatalib.net/. 003 * 004 * AutomataLib is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License version 3.0 as published by the Free Software Foundation. 007 * 008 * AutomataLib is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 011 * Lesser General Public License for more details. 012 * 013 * You should have received a copy of the GNU Lesser General Public 014 * License along with AutomataLib; if not, see 015 * http://www.gnu.de/documents/lgpl.en.html. 016 */ 017package net.automatalib.commons.util.mappings; 018 019import java.util.AbstractCollection; 020import java.util.AbstractList; 021import java.util.Collection; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Map; 025 026/** 027 * Collection of various methods dealing with {@link Mapping}s. 028 * 029 * @author Malte Isberner <malte.isberner@gmail.com> 030 * 031 */ 032public abstract class Mappings { 033 034 private static final Mapping<?,?> NULL_MAPPING = new Mapping<Object,Object>() { 035 @Override 036 public Object get(Object elem) { 037 return null; 038 } 039 }; 040 041 private static final Mapping<?,?> IDENTITY_MAPPING = new Mapping<Object,Object>() { 042 @Override 043 public Object get(Object elem) { 044 return elem; 045 } 046 }; 047 048 private static final Mapping<?,String> TOSTRING_MAPPING = new Mapping<Object,String>() { 049 @Override 050 public String get(Object elem) { 051 return String.valueOf(elem); 052 } 053 }; 054 055 056 /** 057 * Retrieves the <code>null</code> mapping, which maps each domain value 058 * to <code>null</code>. 059 * @param <D> domain class. 060 * @param <R> range class. 061 * @return the <code>null</code> mapping. 062 */ 063 @SuppressWarnings("unchecked") 064 public static <D,R> Mapping<D,R> nullMapping() { 065 return (Mapping<D,R>)NULL_MAPPING; 066 } 067 068 /** 069 * Retrieves the identity mapping, which maps each domain value 070 * to itself. 071 * @param <T> domain/range class. 072 * @return the identity mapping. 073 */ 074 @SuppressWarnings("unchecked") 075 public static <T> Mapping<T,T> identity() { 076 return (Mapping<T,T>)IDENTITY_MAPPING; 077 } 078 079 /** 080 * Returns a mapping that maps objects to their {@link String} representation, 081 * as obtained by {@link String#valueOf(Object)}. 082 * @return the "<tt>toString()</tt>" mapping 083 */ 084 @SuppressWarnings("unchecked") 085 public static <D> Mapping<D,String> toStringMapping() { 086 return (Mapping<D,String>)TOSTRING_MAPPING; 087 } 088 089 /** 090 * Returns a mapping that maps objects to a supertype representation. 091 * @return the "upcast" mapping 092 */ 093 @SuppressWarnings("unchecked") 094 public static <S,T extends S> Mapping<T,S> upcast() { 095 return (Mapping<T,S>)IDENTITY_MAPPING; 096 } 097 098 /** 099 * Retrieves the composition of two mappings, i.e., that mapping that 100 * results from applying the {@link Mapping#get(Object)} method 101 * consecutively. 102 * @param <D> domain class of the first (and resulting) mapping. 103 * @param <I> intermediate object class, range class of the first and domain 104 * class of the second mapping. 105 * @param <R> range class of the second (and resulting) mapping. 106 * @param first first mapping. 107 * @param second second mapping. 108 * @return the composed mapping. 109 */ 110 public static <D,I,R> Mapping<D,R> compose(Mapping<D, ? extends I> first, Mapping<? super I,R> second) { 111 return new MappingComposition<D, I, R>(first, second); 112 } 113 114 115 /** 116 * Applies a mapping to a collection, resulting in a collection containing 117 * the result of applying the specified mapping to each element in the 118 * collection. 119 * 120 * Note that more specific properties of the specified collection won't 121 * be preserved: If the given collection is e.g. a set, and the provided 122 * mapping is not bijective, then the resulting collections may contain 123 * some values multiple times. 124 * 125 * @param <D> domain class. 126 * @param <R> range class. 127 * @param mapping the mapping to apply. 128 * @param coll the collection. 129 * @return the mapped collection. 130 */ 131 public static <D,R> Collection<R> apply(final Mapping<? super D,R> mapping, final Collection<? extends D> coll) { 132 return new AbstractCollection<R>() { 133 @Override 134 public Iterator<R> iterator() { 135 return apply(mapping, coll.iterator()); 136 } 137 138 @Override 139 public int size() { 140 return coll.size(); 141 } 142 }; 143 } 144 145 /** 146 * Applies a mapping to a list, resulting in a list containing the result 147 * of applying the specified mapping to each element in the list. 148 * 149 * @param mapping the mapping to apply. 150 * @param list the list. 151 * @return the mapped list. 152 */ 153 public static <D,R> List<R> apply(final Mapping<? super D,R> mapping, final List<? extends D> list) { 154 return new AbstractList<R>() { 155 /* 156 * (non-Javadoc) 157 * @see java.util.AbstractList#get(int) 158 */ 159 @Override 160 public R get(int index) { 161 return mapping.get(list.get(index)); 162 } 163 164 /* 165 * (non-Javadoc) 166 * @see java.util.AbstractCollection#size() 167 */ 168 @Override 169 public int size() { 170 return list.size(); 171 } 172 }; 173 } 174 175 /** 176 * Applies a mapping to an iterable. The result is an iterable whose 177 * iterator returns the results of applying the specified mapping 178 * to each of the elements returned by the original iterable. 179 * @param <D> domain class. 180 * @param <R> range clas. 181 * @param mapping the mapping to apply. 182 * @param it the underlying iterable. 183 * @return the mapped iterable. 184 */ 185 public static <D,R> Iterable<R> apply(final Mapping<? super D,R> mapping, final Iterable<? extends D> it) { 186 return new Iterable<R>() { 187 @Override 188 public Iterator<R> iterator() { 189 return apply(mapping, it.iterator()); 190 } 191 }; 192 } 193 194 /** 195 * Applies a mapping to an iterator. For the behavior, see 196 * {@link #apply(Mapping, Iterable)}. The resulting iterator supports 197 * each operation which the underlying supports. 198 * 199 * @param <D> domain class. 200 * @param <R> range class. 201 * @param mapping the mapping to apply. 202 * @param baseIt the underlying iterator. 203 * @return the mapped iterator. 204 */ 205 public static <D,R> Iterator<R> apply(Mapping<? super D,R> mapping, Iterator<? extends D> baseIt) { 206 return new MappedIterator<D, R>(mapping, baseIt); 207 } 208 209 210 /** 211 * Safely retrieves a value from a mapping. If the mapping is 212 * <code>null</code> or returns a <code>null</code> value, the given 213 * fallback value is returned. 214 * @param mapping the mapping. 215 * @param key the key. 216 * @param fallback the fallback value to return if either the mapping or the 217 * originally returned value are <code>null</code>. 218 * @return the value returned by the specified mapping, or the fallback value. 219 */ 220 public static <D,R> R safeGet(Mapping<? super D,R> mapping, D key, R fallback) { 221 if(mapping == null) 222 return fallback; 223 R val = mapping.get(key); 224 if(val == null) 225 return fallback; 226 return val; 227 } 228 229 public static <D> D idGet(Mapping<D,D> mapping, D key) { 230 return safeGet(mapping, key, key); 231 } 232 233 public static <D,R> R nullGet(Mapping<? super D,? extends R> mapping, D key) { 234 return safeGet(mapping, key, null); 235 } 236 237 public static <D,R> Mapping<D,R> fromMap(Map<D,R> map) { 238 return new MapMapping<D,R>(map); 239 } 240 241 242 243 /* 244 * Prevent inheritance. 245 */ 246 private Mappings() { 247 } 248}