Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Sa Jan 26 2008 14:11:34 CET
file stats: LOC: 383   Methods: 19
NCLOC: 204   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DefaultModuleAddress.java 38,9% 58,6% 73,7% 55,8%
coverage coverage
 1    /* $Id: DefaultModuleAddress.java,v 1.6 2008/01/26 12:39:08 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2007, Michael Meyling <mime@qedeq.org>.
 6    *
 7    * "Hilbert II" is free software; you can redistribute
 8    * it and/or modify it under the terms of the GNU General Public
 9    * License as published by the Free Software Foundation; either
 10    * version 2 of the License, or (at your option) any later version.
 11    *
 12    * This program is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15    * GNU General Public License for more details.
 16    */
 17   
 18    package org.qedeq.kernel.bo.load;
 19   
 20    import java.io.File;
 21    import java.io.IOException;
 22    import java.net.MalformedURLException;
 23    import java.net.URL;
 24   
 25    import org.qedeq.kernel.base.module.LocationList;
 26    import org.qedeq.kernel.base.module.Specification;
 27    import org.qedeq.kernel.bo.module.ModuleAddress;
 28    import org.qedeq.kernel.bo.module.ModuleContext;
 29    import org.qedeq.kernel.trace.Trace;
 30    import org.qedeq.kernel.utility.IoUtility;
 31   
 32   
 33    /**
 34    * An object of this class represents an address for a QEDEQ module.
 35    *
 36    * @version $Revision: 1.6 $
 37    * @author Michael Meyling
 38    */
 39    public class DefaultModuleAddress implements ModuleAddress {
 40   
 41    /** This class. */
 42    private static final Class CLASS = DefaultModuleAddress.class;
 43   
 44    /** URL form of this address. */
 45    private final URL url;
 46   
 47    /** Header (including protocol, host, port, user) but without file path. */
 48    private final String header;
 49   
 50    /** Path (without protocol, host, port and file name). */
 51    private final String path;
 52   
 53    /** File name of QEDEQ module including <code>.xml</code>. */
 54    private final String fileName;
 55   
 56    /** Is module address relative? */
 57    private final boolean relativeAddress;
 58   
 59    /** Is module address a file? */
 60    private final boolean fileAddress;
 61   
 62    /** Module name. That is file name without <code>.xml</code> */
 63    private final String name;
 64   
 65    /**
 66    * Constructor.
 67    *
 68    * @param u Address of module.
 69    * @throws IOException if address is formally incorrect
 70    */
 71  423 public DefaultModuleAddress(final String u)
 72    throws IOException {
 73   
 74  423 this(u, (DefaultModuleAddress) null);
 75    }
 76   
 77    /**
 78    * Constructor.
 79    *
 80    * @param u Address of module.
 81    * @throws IOException if address is formally incorrect
 82    */
 83  49 public DefaultModuleAddress(final URL u) throws IOException {
 84  49 this(u.toExternalForm(), (DefaultModuleAddress) null);
 85    }
 86   
 87    /**
 88    * Constructor.
 89    *
 90    * @param file File path of module.
 91    * @throws IOException Address is formally incorrect
 92    */
 93  2 public DefaultModuleAddress(final File file)
 94    throws IOException {
 95  2 this(IoUtility.toUrl(file));
 96    }
 97   
 98    /**
 99    * Constructor.
 100    *
 101    * @param address Address of module.
 102    * @param parent Address of parent module.
 103    * @throws MalformedURLException Address is formally incorrect.
 104    */
 105  566 public DefaultModuleAddress(final String address, final ModuleAddress parent)
 106    throws MalformedURLException {
 107  566 final String method = "ModuleAddress(String, ModuleAddress)";
 108  566 if (address == null) {
 109  0 throw new NullPointerException();
 110    }
 111  566 URL urmel;
 112  566 try {
 113  566 if (parent != null) {
 114  94 urmel = new URL(parent.getURL(), address);
 115    } else {
 116  472 urmel = new URL(address);
 117    }
 118    } catch (MalformedURLException e) {
 119  4 Trace.trace(CLASS, this, method, "address=" + address);
 120  4 Trace.trace(CLASS, this, method, "parent=" + parent);
 121  4 Trace.trace(CLASS, this, method, e);
 122  4 try {
 123  4 final String newAddress = "file:" + address;
 124  4 if (parent != null) {
 125  0 urmel = new URL(parent.getURL(), newAddress);
 126    } else {
 127  4 urmel = new URL(newAddress);
 128    }
 129    } catch (MalformedURLException ex) {
 130  0 throw e; // throw original exception
 131    }
 132    }
 133  566 Trace.trace(CLASS, this, method, "protocol=" + urmel.getProtocol());
 134  566 url = urmel;
 135  566 fileAddress = url.getProtocol().equalsIgnoreCase("file");
 136    /*
 137    Trace.trace(this, METHOD, "url.getFile=" + this.url.getFile());
 138    Trace.trace(this, METHOD, "url.getPath=" + this.url.getPath());
 139    try {
 140    Trace.trace(this, METHOD, "URI File=" +
 141    new File(new URI(this.address)).getAbsoluteFile());
 142    } catch (URISyntaxException e1) {
 143    e1.printStackTrace();
 144    }
 145    */
 146  566 final String p = urmel.getFile();
 147  566 final int position = p.lastIndexOf("/");
 148  566 if (position >= 0 && position + 1 < p.length()) {
 149  566 this.path = p.substring(0, position) + "/";
 150  566 this.fileName = p.substring(position + 1);
 151    } else {
 152  0 this.path = "";
 153  0 this.fileName = p;
 154    }
 155  566 Trace.trace(CLASS, this, method, "path=" + this.path);
 156  566 Trace.trace(CLASS, this, method, "fileName=" + this.fileName);
 157  566 this.relativeAddress = !this.path.startsWith("/");
 158  566 if (!this.fileName.endsWith(".xml")) {
 159  0 throw new MalformedURLException("file name doesn't end with \".xml\": "
 160    + this.fileName);
 161    }
 162  566 final int positionBefore = this.fileName.lastIndexOf(".");
 163  566 final String mname = this.fileName.substring(0, positionBefore);
 164  566 this.name = mname;
 165  566 final int positionPath
 166    = url.toString().lastIndexOf(this.path + this.fileName);
 167  566 if (positionPath < 0) {
 168  0 throw new IllegalArgumentException(
 169    "couldn't determine begin of file path: "
 170    + url.toString());
 171    }
 172  566 this.header = url.toString().substring(0, positionPath);
 173    }
 174   
 175    /**
 176    * Get module address as {@link ModuleContext}. Creates a new object.
 177    *
 178    * @return Module address as {@link ModuleContext}.
 179    */
 180  32493 public final ModuleContext createModuleContext() {
 181  32493 return new ModuleContext(this);
 182    }
 183   
 184    /**
 185    * Get address header (including protocol, host, port, user)
 186    * but without file path.
 187    *
 188    * @return address header
 189    */
 190  0 public final String getHeader() {
 191  0 return header;
 192    }
 193   
 194    /**
 195    * Get address path (without protocol, host, port and file name).
 196    *
 197    * @return module path
 198    */
 199  0 public final String getPath() {
 200  0 return path;
 201    }
 202   
 203    /**
 204    * Get module file name.
 205    *
 206    * @return Module file name.
 207    */
 208  446 public final String getFileName() {
 209  446 return fileName;
 210    }
 211   
 212    /**
 213    * Get name of module (file name without <code>.xml</code>).
 214    *
 215    * @return Module name.
 216    */
 217  2248 public final String getName() {
 218  2248 return this.name;
 219    }
 220   
 221    /**
 222    * Get fully qualified URL of module.
 223    *
 224    * @return URL for QEDEQ module.
 225    */
 226  53605 public final URL getURL() {
 227  53605 return this.url;
 228    }
 229   
 230    /**
 231    * Was this module address created relatively?
 232    *
 233    * @return Relatively created?
 234    */
 235  0 public final boolean isRelativeAddress() {
 236  0 return this.relativeAddress;
 237    }
 238   
 239    /**
 240    * Is this a local QEDEQ file. That means the address starts with <code>file:</code>.
 241    *
 242    * @return Is the QEDEQ module a local file?
 243    */
 244  25198 public final boolean isFileAddress() {
 245  25198 return fileAddress;
 246    }
 247   
 248  32523 public final String toString() {
 249  32523 return url.toString();
 250    }
 251   
 252  1368 public final int hashCode() {
 253  1368 return url.hashCode();
 254    }
 255   
 256  112 public final boolean equals(final Object object) {
 257  112 if (object == null || !(object instanceof DefaultModuleAddress)) {
 258  2 return false;
 259    }
 260  110 return url.equals(((DefaultModuleAddress) object).url);
 261    }
 262   
 263    /**
 264    * Get the file name of the specified module.
 265    *
 266    * TODO mime 20070326: is this function really necessary?
 267    *
 268    * @param spec here are the (perhaps relative) addresses to
 269    * another module
 270    * @return file name of specified module
 271    */
 272  65 public static final String getModuleFileName(final Specification spec) {
 273   
 274  65 return spec.getName() + ".xml";
 275    }
 276   
 277    /**
 278    * Get all potential module addresses from a module specification.
 279    *
 280    * TODO mime 20070326: add context information (for error case)
 281    *
 282    * @param address Starting from that module address.
 283    * @param spec Here are the (perhaps relative) addresses to
 284    * another module.
 285    * @return Array of absolute address strings.
 286    * @throws IOException One address is not correctly formed.
 287    */
 288  65 public static final ModuleAddress[] getModulePaths(final ModuleAddress address,
 289    final Specification spec) throws IOException {
 290   
 291  65 final String fileNameEnd = getModuleFileName(spec);
 292  65 final LocationList locations = spec.getLocationList();
 293  65 final ModuleAddress[] result
 294    = new ModuleAddress[locations.size()];
 295  65 for (int i = 0; i < locations.size(); i++) {
 296  94 String fileName
 297    = locations.get(i).getLocation();
 298  94 if (fileName.equals(".")) {
 299  65 fileName = "";
 300  29 } else if (!fileName.endsWith("/")) {
 301  29 fileName += "/";
 302    }
 303  94 fileName += fileNameEnd;
 304  94 result[i] = new DefaultModuleAddress(fileName, address);
 305    }
 306  65 return result;
 307    }
 308   
 309    /**
 310    * Create relative address from <code>orgin</code> to <code>next</code>.
 311    *
 312    * @param origin This is the original location (URL!).
 313    * @param next This should be the next location (URL!).
 314    * @return Relative (or if necessary absolute) address.
 315    */
 316  0 public static final String createRelativeAddress(final String origin,
 317    final String next) {
 318  0 if (origin.equals(next)) {
 319  0 return "";
 320    }
 321  0 try {
 322  0 final URL urlOrgin = new URL(origin);
 323  0 final URL urlNext = new URL(next);
 324   
 325  0 if (urlOrgin.getProtocol().equals(urlNext.getProtocol())
 326    && urlOrgin.getHost().equals(urlNext.getHost())
 327    && urlOrgin.getPort() == urlNext.getPort()) {
 328  0 final String org = urlOrgin.getFile();
 329  0 final String nex = urlNext.getFile();
 330  0 int i = -1; // position of next '/'
 331  0 int j = 0; // position of last '/'
 332  0 while (0 <= (i = org.indexOf("/", j))) {
 333  0 if (i >= 0 && nex.length() > i
 334    && org.substring(j, i).equals(
 335    nex.substring(j, i))) {
 336  0 j = i + 1;
 337    } else {
 338  0 break;
 339    }
 340    }
 341  0 if (j > 0) {
 342  0 i = j;
 343  0 StringBuffer result = new StringBuffer(nex.length());
 344  0 while (0 <= (i = org.indexOf("/", i))) {
 345  0 i++;
 346  0 result.append("../");
 347    }
 348  0 result.append(nex.substring(j));
 349  0 return result.toString();
 350    } else {
 351  0 return "/" + nex;
 352    }
 353    } else { // no relative address possible
 354  0 return urlNext.toString();
 355    }
 356    } catch (MalformedURLException e) {
 357  0 return next;
 358    }
 359   
 360    }
 361   
 362    /**
 363    * Get module address with new ending. E.g.: ".html" instead of ".qedeq".
 364    *
 365    * @param address The address of something (e.g.: a module).
 366    * @param newEnding This should be the new ending (e.g.: "html").
 367    * @return module address with substituted ending
 368    */
 369  0 public static final String newEnding(final String address,
 370    final String newEnding) {
 371  0 if (address.length() == 0) {
 372  0 return "";
 373    }
 374  0 final int i = address.lastIndexOf(".");
 375  0 if (i > 0) {
 376  0 return address.substring(0, i + 1) + newEnding;
 377    } else {
 378  0 return address + "." + newEnding;
 379    }
 380    }
 381   
 382    }
 383