diff options
Diffstat (limited to 'src/cuchaz/enigma/convert/ClassMatching.java')
| -rw-r--r-- | src/cuchaz/enigma/convert/ClassMatching.java | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/convert/ClassMatching.java b/src/cuchaz/enigma/convert/ClassMatching.java new file mode 100644 index 0000000..fea8438 --- /dev/null +++ b/src/cuchaz/enigma/convert/ClassMatching.java | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.convert; | ||
| 12 | |||
| 13 | import java.util.ArrayList; | ||
| 14 | import java.util.Collection; | ||
| 15 | import java.util.List; | ||
| 16 | import java.util.Map; | ||
| 17 | |||
| 18 | import com.beust.jcommander.internal.Lists; | ||
| 19 | import com.google.common.collect.ArrayListMultimap; | ||
| 20 | import com.google.common.collect.BiMap; | ||
| 21 | import com.google.common.collect.HashBiMap; | ||
| 22 | import com.google.common.collect.Multimap; | ||
| 23 | |||
| 24 | public class ClassMatching | ||
| 25 | { | ||
| 26 | private Multimap<ClassIdentity,ClassIdentity> m_sourceClasses; | ||
| 27 | private Multimap<ClassIdentity,ClassIdentity> m_matchedDestClasses; | ||
| 28 | private List<ClassIdentity> m_unmatchedDestClasses; | ||
| 29 | |||
| 30 | public ClassMatching( ) | ||
| 31 | { | ||
| 32 | m_sourceClasses = ArrayListMultimap.create(); | ||
| 33 | m_matchedDestClasses = ArrayListMultimap.create(); | ||
| 34 | m_unmatchedDestClasses = Lists.newArrayList(); | ||
| 35 | } | ||
| 36 | |||
| 37 | public void addSource( ClassIdentity c ) | ||
| 38 | { | ||
| 39 | m_sourceClasses.put( c, c ); | ||
| 40 | } | ||
| 41 | |||
| 42 | public void matchDestClass( ClassIdentity destClass ) | ||
| 43 | { | ||
| 44 | Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get( destClass ); | ||
| 45 | if( matchedSourceClasses.isEmpty() ) | ||
| 46 | { | ||
| 47 | // no match | ||
| 48 | m_unmatchedDestClasses.add( destClass ); | ||
| 49 | } | ||
| 50 | else | ||
| 51 | { | ||
| 52 | // found a match | ||
| 53 | m_matchedDestClasses.put( destClass, destClass ); | ||
| 54 | |||
| 55 | // DEBUG | ||
| 56 | ClassIdentity sourceClass = matchedSourceClasses.iterator().next(); | ||
| 57 | assert( sourceClass.hashCode() == destClass.hashCode() ); | ||
| 58 | assert( sourceClass.equals( destClass ) ); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | public void removeSource( ClassIdentity sourceClass ) | ||
| 63 | { | ||
| 64 | m_sourceClasses.remove( sourceClass, sourceClass ); | ||
| 65 | } | ||
| 66 | |||
| 67 | public void removeDest( ClassIdentity destClass ) | ||
| 68 | { | ||
| 69 | m_matchedDestClasses.remove( destClass, destClass ); | ||
| 70 | m_unmatchedDestClasses.remove( destClass ); | ||
| 71 | } | ||
| 72 | |||
| 73 | public List<ClassIdentity> getSourceClasses( ) | ||
| 74 | { | ||
| 75 | return new ArrayList<ClassIdentity>( m_sourceClasses.values() ); | ||
| 76 | } | ||
| 77 | |||
| 78 | public List<ClassIdentity> getDestClasses( ) | ||
| 79 | { | ||
| 80 | List<ClassIdentity> classes = Lists.newArrayList(); | ||
| 81 | classes.addAll( m_matchedDestClasses.values() ); | ||
| 82 | classes.addAll( m_unmatchedDestClasses ); | ||
| 83 | return classes; | ||
| 84 | } | ||
| 85 | |||
| 86 | public BiMap<ClassIdentity,ClassIdentity> getUniqueMatches( ) | ||
| 87 | { | ||
| 88 | BiMap<ClassIdentity,ClassIdentity> uniqueMatches = HashBiMap.create(); | ||
| 89 | for( ClassIdentity sourceClass : m_sourceClasses.keySet() ) | ||
| 90 | { | ||
| 91 | Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get( sourceClass ); | ||
| 92 | Collection<ClassIdentity> matchedDestClasses = m_matchedDestClasses.get( sourceClass ); | ||
| 93 | if( matchedSourceClasses.size() == 1 && matchedDestClasses.size() == 1 ) | ||
| 94 | { | ||
| 95 | ClassIdentity matchedSourceClass = matchedSourceClasses.iterator().next(); | ||
| 96 | ClassIdentity matchedDestClass = matchedSourceClasses.iterator().next(); | ||
| 97 | uniqueMatches.put( matchedSourceClass, matchedDestClass ); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | return uniqueMatches; | ||
| 101 | } | ||
| 102 | |||
| 103 | public BiMap<List<ClassIdentity>,List<ClassIdentity>> getAmbiguousMatches( ) | ||
| 104 | { | ||
| 105 | BiMap<List<ClassIdentity>,List<ClassIdentity>> ambiguousMatches = HashBiMap.create(); | ||
| 106 | for( ClassIdentity sourceClass : m_sourceClasses.keySet() ) | ||
| 107 | { | ||
| 108 | Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get( sourceClass ); | ||
| 109 | Collection<ClassIdentity> matchedDestClasses = m_matchedDestClasses.get( sourceClass ); | ||
| 110 | if( matchedSourceClasses.size() > 1 && matchedDestClasses.size() > 1 ) | ||
| 111 | { | ||
| 112 | ambiguousMatches.put( | ||
| 113 | new ArrayList<ClassIdentity>( matchedSourceClasses ), | ||
| 114 | new ArrayList<ClassIdentity>( matchedDestClasses ) | ||
| 115 | ); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | return ambiguousMatches; | ||
| 119 | } | ||
| 120 | |||
| 121 | public int getNumAmbiguousSourceMatches( ) | ||
| 122 | { | ||
| 123 | int num = 0; | ||
| 124 | for( Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet() ) | ||
| 125 | { | ||
| 126 | num += entry.getKey().size(); | ||
| 127 | } | ||
| 128 | return num; | ||
| 129 | } | ||
| 130 | |||
| 131 | public int getNumAmbiguousDestMatches( ) | ||
| 132 | { | ||
| 133 | int num = 0; | ||
| 134 | for( Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet() ) | ||
| 135 | { | ||
| 136 | num += entry.getValue().size(); | ||
| 137 | } | ||
| 138 | return num; | ||
| 139 | } | ||
| 140 | |||
| 141 | public List<ClassIdentity> getUnmatchedSourceClasses( ) | ||
| 142 | { | ||
| 143 | List<ClassIdentity> classes = Lists.newArrayList(); | ||
| 144 | for( ClassIdentity sourceClass : getSourceClasses() ) | ||
| 145 | { | ||
| 146 | if( m_matchedDestClasses.get( sourceClass ).isEmpty() ) | ||
| 147 | { | ||
| 148 | classes.add( sourceClass ); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | return classes; | ||
| 152 | } | ||
| 153 | |||
| 154 | public List<ClassIdentity> getUnmatchedDestClasses( ) | ||
| 155 | { | ||
| 156 | return new ArrayList<ClassIdentity>( m_unmatchedDestClasses ); | ||
| 157 | } | ||
| 158 | |||
| 159 | @Override | ||
| 160 | public String toString( ) | ||
| 161 | { | ||
| 162 | StringBuilder buf = new StringBuilder(); | ||
| 163 | |||
| 164 | buf.append( "Source classes: " ); | ||
| 165 | buf.append( getSourceClasses().size() ); | ||
| 166 | buf.append( "\n\tUnique: " ); | ||
| 167 | buf.append( getUniqueMatches().size() ); | ||
| 168 | buf.append( "\n\tAmbiguous: " ); | ||
| 169 | buf.append( getNumAmbiguousSourceMatches() ); | ||
| 170 | buf.append( "\n\tUnmatched: " ); | ||
| 171 | buf.append( getUnmatchedSourceClasses().size() ); | ||
| 172 | |||
| 173 | buf.append( "\nDest classes: " ); | ||
| 174 | buf.append( getDestClasses().size() ); | ||
| 175 | buf.append( "\n\tUnique: " ); | ||
| 176 | buf.append( getUniqueMatches().size() ); | ||
| 177 | buf.append( "\n\tAmbiguous: " ); | ||
| 178 | buf.append( getNumAmbiguousDestMatches() ); | ||
| 179 | buf.append( "\n\tUnmatched: " ); | ||
| 180 | buf.append( getUnmatchedDestClasses().size() ); | ||
| 181 | |||
| 182 | return buf.toString(); | ||
| 183 | } | ||
| 184 | } | ||