Add javadoc, suppress warnings.
[WoTNS.git] / src / main / java / net / pterodactylus / wotns / main / Resolver.java
1 /*
2  * WoTNS - Resolver.java - Copyright © 2011 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.wotns.main;
19
20 import java.net.MalformedURLException;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.List;
25 import java.util.Set;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import net.pterodactylus.util.logging.Logging;
30 import net.pterodactylus.util.object.Default;
31 import net.pterodactylus.wotns.freenet.wot.Identity;
32 import net.pterodactylus.wotns.freenet.wot.IdentityManager;
33 import net.pterodactylus.wotns.freenet.wot.OwnIdentity;
34 import net.pterodactylus.wotns.freenet.wot.Trust;
35 import freenet.keys.FreenetURI;
36
37 /**
38  * Resolves short names as given by the user.
39  * <p>
40  * Short names generally have the syntax:
41  *
42  * <pre>
43  * identity [ ‘@’ start-of-key ] ‘/’ target [ ‘/’ file-path ]
44  * </pre>
45  * <p>
46  * Because resolving a short name is based on the <i>web</i> of trust, the ID of
47  * an own identity must be given in order to find the entry point into the web
48  * of trust. If no ID is specified, the ID of a random own identity is used. If
49  * no own identity exists, short names can not be resolved.
50  *
51  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
52  */
53 public class Resolver {
54
55         /** The logger. */
56         private static final Logger logger = Logging.getLogger(Resolver.class);
57
58         /** The identity manager. */
59         private final IdentityManager identityManager;
60
61         /** The ID of the own identity to use for resolving. */
62         private String ownIdentityId;
63
64         /**
65          * Creates a new resolver.
66          *
67          * @param identityManager
68          *            The identity manager to use
69          */
70         public Resolver(IdentityManager identityManager) {
71                 this.identityManager = identityManager;
72         }
73
74         //
75         // ACCESSORS
76         //
77
78         /**
79          * Returns the ID of the own identity used for resolving short names.
80          *
81          * @return The ID of the own identity used for resolving
82          */
83         public String getOwnIdentityId() {
84                 return ownIdentityId;
85         }
86
87         /**
88          * Sets the ID of the own identity used for resolving short names.
89          *
90          * @param ownIdentityId
91          *            The ID of the own identity used for resolving
92          */
93         public void setOwnIdentityId(String ownIdentityId) {
94                 this.ownIdentityId = ownIdentityId;
95         }
96
97         //
98         // ACTIONS
99         //
100
101         /**
102          * Resolves a short name.
103          *
104          * @param shortUri
105          *            The short name to resolve
106          * @return The Freenet URI the short name resolves to, or {@code null} if
107          *         the short name can not be resolved
108          * @throws MalformedURLException
109          *             if the short name is malformed
110          */
111         public FreenetURI resolveURI(String shortUri) throws MalformedURLException {
112                 int firstSlash = shortUri.indexOf('/');
113                 if (firstSlash == -1) {
114                         throw new MalformedURLException("At least one slash is required.");
115                 }
116                 String shortName = shortUri.substring(0, firstSlash);
117                 String target = shortUri.substring(firstSlash + 1);
118                 Identity identity = locateIdentity(shortName);
119                 System.out.println("located identity: " + identity);
120                 if (identity == null) {
121                         return null;
122                 }
123                 return new FreenetURI(identity.getProperty("tns." + target));
124         }
125
126         //
127         // PRIVATE METHODS
128         //
129
130         /**
131          * Locates the identity specified by the given short name. If more than one
132          * identity matches the given pattern, the one with the highest trust is
133          * used. When calculating the trust, local and remote trust are treated
134          * equally, i.e. the higher value of either one is used.
135          *
136          * @param shortName
137          *            The short name to locate an identity for
138          * @return The located identity, or {@code null} if no identity can be
139          *         found, or if no own identity is found to use for locating an
140          *         identity
141          */
142         private Identity locateIdentity(String shortName) {
143                 int atSign = shortName.indexOf('@');
144                 String identityName = shortName;
145                 String keyStart = "";
146                 if (atSign > -1) {
147                         identityName = shortName.substring(0, atSign);
148                         keyStart = shortName.substring(atSign + 1);
149                 }
150                 final OwnIdentity ownIdentity;
151                 if (this.ownIdentityId != null) {
152                         if (identityManager.getOwnIdentity(this.ownIdentityId) != null) {
153                                 ownIdentity = identityManager.getOwnIdentity(this.ownIdentityId);
154                         } else {
155                                 ownIdentity = getFirstOwnIdentity();
156                         }
157                 } else {
158                         ownIdentity = getFirstOwnIdentity();
159                 }
160                 if (ownIdentity == null) {
161                         logger.log(Level.SEVERE, "Can not resolve “" + shortName + "” without a Web of Trust Identity!");
162                         return null;
163                 }
164                 System.out.println("using own identity " + ownIdentity + " to resolve " + shortName);
165                 Set<Identity> trustedIdentities = Default.forNull(identityManager.getTrustedIdentities(ownIdentity), Collections.<Identity> emptySet());
166                 List<Identity> matchingIdentities = new ArrayList<Identity>();
167                 System.out.println("checking " + trustedIdentities);
168                 for (Identity identity : trustedIdentities) {
169                         if (identity.getNickname().equals(identityName) && identity.getId().startsWith(keyStart)) {
170                                 matchingIdentities.add(identity);
171                         }
172                 }
173                 if (matchingIdentities.isEmpty()) {
174                         return null;
175                 }
176                 Collections.sort(matchingIdentities, new Comparator<Identity>() {
177
178                         @Override
179                         public int compare(Identity leftIdentity, Identity rightIdentity) {
180                                 Trust leftTrust = leftIdentity.getTrust(ownIdentity);
181                                 Trust rightTrust = rightIdentity.getTrust(ownIdentity);
182                                 int leftTrustCombined = ((leftTrust.getExplicit() != null) ? leftTrust.getExplicit() : 0) + ((leftTrust.getImplicit() != null) ? leftTrust.getImplicit() : 0);
183                                 int rightTrustCombined = ((rightTrust.getExplicit() != null) ? rightTrust.getExplicit() : 0) + ((rightTrust.getImplicit() != null) ? rightTrust.getImplicit() : 0);
184                                 return leftTrustCombined - rightTrustCombined;
185                         }
186                 });
187                 return matchingIdentities.get(0);
188         }
189
190         /**
191          * Returns a random own identity from the web of trust.
192          *
193          * @return A random own identity from the web of trust, or {@code null} if
194          *         the web of trust does not have any own identities
195          */
196         private OwnIdentity getFirstOwnIdentity() {
197                 Set<OwnIdentity> ownIdentities = identityManager.getAllOwnIdentities();
198                 if (!ownIdentities.isEmpty()) {
199                         return ownIdentities.iterator().next();
200                 }
201                 return null;
202         }
203
204 }