/* Copyright (C) 2006 Christian Schneider * * This file is part of Nomad. * * Nomad 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 2 of the License, or * (at your option) any later version. * * Nomad 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 Nomad; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package net.sf.nmedit.jpatch.transform; import java.io.IOException; import java.io.Serializable; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import net.sf.nmedit.jpatch.PConnectorDescriptor; import net.sf.nmedit.jpatch.PModule; import net.sf.nmedit.jpatch.PModuleDescriptor; import net.sf.nmedit.jpatch.PParameterDescriptor; /** * Implements {@link PTTransformations}. * * @author Christian Schneider */ public class PTBasicTransformations implements PTTransformations { /** * Empty list. */ private static final List<PTModuleSelector> EMPTY = Collections.<PTModuleSelector>emptyList(); /** * Empty array. */ private static final PParameterDescriptor[] EMPTYP = new PParameterDescriptor[0]; /** * Empty array. */ private static final PConnectorDescriptor[] EMPTYC = new PConnectorDescriptor[0]; /** * Sorts the specified array. The elements are ordered * descending by the {@link PTModuleMapping#getCovering()} value. * @param mappings the elements to sort */ public static void sort(PTModuleMapping[] mappings) { Arrays.sort(mappings, new MappingOrder()); } /** * Compares two mappings and orders them * descending by the {@link PTModuleMapping#getCovering()} value. */ private static class MappingOrder implements Comparator<PTModuleMapping>, Serializable { /** * */ private static final long serialVersionUID = 6633285776526783275L; /** * Compares two mappings and orders them * descending by the {@link PTModuleMapping#getCovering()} value. */ public int compare(PTModuleMapping o1, PTModuleMapping o2) { double c1 = o1.getCovering(); double c2 = o2.getCovering(); return (int) Math.signum(c2-c1); } private void writeObject(java.io.ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); } } private PTModuleSelector[] selectors; private SoftReference<Map<Object, List<PTModuleSelector>>> mapRef; public PTBasicTransformations(PTModuleSelector[] selectors) { this.selectors = selectors; } private Map<Object, List<PTModuleSelector>> getMap() { Map<Object, List<PTModuleSelector>> map = mapRef == null ? null : mapRef.get(); if (map == null) { map = new HashMap<Object, List<PTModuleSelector>>(selectors.length); mapRef = new SoftReference<Map<Object,List<PTModuleSelector>>>(map); } return map; } private List<PTModuleSelector> getGraph(PModuleDescriptor module) { Map<Object, List<PTModuleSelector>> map = getMap(); List<PTModuleSelector> list = map.get(module.getComponentId()); if (list != null) return list; PTModuleSelector selector = null; for (int i=selectors.length-1;i>=0;i--) { PTModuleSelector s = selectors[i]; if (s.getDescriptor().getComponentId().equals(module.getComponentId())) { selector = s; break; } } if (selector == null) { map.put(module.getComponentId(), EMPTY); return EMPTY; } list = new ArrayList<PTModuleSelector>(); for (PTModuleSelector m: selectors) if (m.intersects(selector)) list.add(m); if (list.size() <= 1) list = EMPTY; map.put(module.getComponentId(), list); return list; } private PTModuleMapping getMapping(List<PTModuleSelector> g, PModuleDescriptor src, PModuleDescriptor dst) { // find the source/target selector PTModuleSelector ssrc = null; PTModuleSelector sdst = null; for (PTModuleSelector s: g) { Object id = s.getDescriptor().getComponentId(); if (src.getComponentId().equals(id)) { ssrc = s; if (sdst != null) break; } else if (dst.getComponentId().equals(id)) { sdst = s; if (ssrc != null) break; } } if (ssrc == null || sdst == null) return null; // now collect matching pairs List<PParameterDescriptor> plist = null; List<PConnectorDescriptor> clist = null; for (PTSelector a: ssrc) { for (PTSelector b: sdst) { if (a.getSelectorId() == b.getSelectorId()) { if (a.getType() == PTSelector.CONNECTOR) { if (clist == null) clist = new LinkedList<PConnectorDescriptor>(); clist.add(a.getConnector()); clist.add(b.getConnector()); } else if (a.getType() == PTSelector.PARAMETER) { if (plist == null) plist = new LinkedList<PParameterDescriptor>(); plist.add(a.getParameter()); plist.add(b.getParameter()); } } } } if (plist == null && clist == null) return null; return new PTModuleMapping(ssrc.getDescriptor(), sdst.getDescriptor(), plist == null ? EMPTYP : plist.toArray(new PParameterDescriptor[plist.size()]), clist == null ? EMPTYC : clist.toArray(new PConnectorDescriptor[clist.size()]) ); } public PTModuleMapping getMapping(PModuleDescriptor source, PModuleDescriptor destination) { List<PTModuleSelector> g = getGraph(source); if (g != null) return getMapping(g, source, destination); return null; } public PTModuleMapping getMapping(PModule source, PModuleDescriptor destination) { return getMapping(source.getDescriptor(), destination); } public PTModuleMapping[] getMappings(PModuleDescriptor source) { List<PTModuleSelector> g = getGraph(source); if (g == null || g.isEmpty()) return new PTModuleMapping[0]; List<PTModuleMapping> mappings = new ArrayList<PTModuleMapping>(g.size()); for (PTModuleSelector sel: g) { if (!sel.getDescriptor().getComponentId().equals(source.getComponentId())) { PTModuleMapping m = getMapping(g, source, sel.getDescriptor()); if (m != null) mappings.add(m); } } return mappings.toArray(new PTModuleMapping[mappings.size()]); } public PModuleDescriptor[] getTargets(PModuleDescriptor source) { List<PTModuleSelector> list = getGraph(source); PModuleDescriptor[] res = new PModuleDescriptor[list.size()]; for (int i=list.size()-1;i>=0;i--) res[i] = list.get(i).getDescriptor(); return res; } }