1 /*
2  * Copyright (C) 2008 XStream Committers.
3  * All rights reserved.
4  *
5  * The software in this package is published under the terms of the BSD
6  * style license a copy of which has been included with this distribution in
7  * the LICENSE.txt file.
8  * 
9  * Created on 10. November 2008 by Joerg Schaible
10  */

11 package com.thoughtworks.xstream.mapper;
12
13 import java.io.IOException;
14 import java.io.ObjectInputStream;
15 import java.io.ObjectOutputStream;
16 import java.io.Serializable;
17 import java.util.Comparator;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.Map;
21 import java.util.TreeMap;
22
23
24 /**
25  * Mapper that allows a package name to be replaced with an alias.
26  * 
27  * @author Jörg Schaible
28  */

29 public class PackageAliasingMapper extends MapperWrapper implements Serializable {
30
31     private static final Comparator REVERSE = new Comparator() {
32
33         public int compare(final Object o1, final Object o2) {
34             return ((String)o2).compareTo((String)o1);
35         }
36     };
37
38     private Map packageToName = new TreeMap(REVERSE);
39     protected transient Map nameToPackage = new HashMap();
40
41     public PackageAliasingMapper(final Mapper wrapped) {
42         super(wrapped);
43     }
44
45     public void addPackageAlias(String name, String pkg) {
46         if (name.length() > 0 && name.charAt(name.length() - 1) != '.') {
47             name += '.';
48         }
49         if (pkg.length() > 0 && pkg.charAt(pkg.length() - 1) != '.') {
50             pkg += '.';
51         }
52         nameToPackage.put(name, pkg);
53         packageToName.put(pkg, name);
54     }
55
56     public String serializedClass(final Class type) {
57         final String className = type.getName();
58         int length = className.length();
59         int dot = -1;
60         do {
61             dot = className.lastIndexOf('.', length);
62             final String pkg = dot < 0 ? "" : className.substring(0, dot + 1);
63             final String alias = (String)packageToName.get(pkg);
64             if (alias != null) {
65                 return alias + (dot < 0 ? className : className.substring(dot + 1));
66             }
67             length = dot - 1;
68         } while (dot >= 0);
69         return super.serializedClass(type);
70     }
71
72     public Class realClass(String elementName) {
73         int length = elementName.length();
74         int dot = -1;
75         do {
76             dot = elementName.lastIndexOf('.', length);
77             final String name = dot < 0 ? "" : elementName.substring(0, dot) + '.';
78             final String packageName = (String)nameToPackage.get(name);
79
80             if (packageName != null) {
81                 elementName = packageName
82                     + (dot < 0 ? elementName : elementName.substring(dot + 1));
83                 break;
84             }
85             length = dot - 1;
86         } while (dot >= 0);
87
88         return super.realClass(elementName);
89     }
90
91     private void writeObject(final ObjectOutputStream out) throws IOException {
92         out.writeObject(new HashMap(packageToName));
93     }
94
95     private void readObject(final ObjectInputStream in)
96         throws IOException, ClassNotFoundException {
97         packageToName = new TreeMap(REVERSE);
98         packageToName.putAll((Map)in.readObject());
99         nameToPackage = new HashMap();
100         for (final Iterator iter = packageToName.keySet().iterator(); iter.hasNext();) {
101             final Object type = iter.next();
102             nameToPackage.put(packageToName.get(type), type);
103         }
104     }
105 }
106