001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.ivy.core.module.id;
019:
020: import java.util.Map;
021: import java.util.WeakHashMap;
022: import java.util.regex.Matcher;
023: import java.util.regex.Pattern;
024:
025: /**
026: * Identifies a module, without revision information
027: *
028: * @see <a href="package-summary.html">org.apache.ivy.core.module.id</a>
029: */
030: public class ModuleId implements Comparable {
031: static final String ENCODE_SEPARATOR = ":#@#:";
032:
033: private static final Map/*<ModuleId, ModuleId>*/CACHE = new WeakHashMap();
034:
035: /**
036: * Returns a ModuleId for the given organization and module name.
037: *
038: * @param org
039: * the module's organization, can be <code>null</code>
040: * @param name
041: * the module's name, must not be <code>null</code>
042: * @return a ModuleId instance
043: */
044: public static ModuleId newInstance(String org, String name) {
045: return intern(new ModuleId(org, name));
046: }
047:
048: /**
049: * Returns an intern instance of a ModuleId equals to the given ModuleId if any, or the given
050: * ModuleId.
051: * <p>
052: * This is useful to reduce the number of instances of ModuleId kept in memory, and thus reduce
053: * memory footprint.
054: * </p>
055: *
056: * @param moduleId
057: * the module id to return
058: * @return a unit instance of the given module id.
059: */
060: public static ModuleId intern(ModuleId moduleId) {
061: ModuleId r = (ModuleId) CACHE.get(moduleId);
062: if (r == null) {
063: r = moduleId;
064: CACHE.put(r, r);
065: }
066: return r;
067: }
068:
069: private String organisation;
070:
071: private String name;
072:
073: private int hash;
074:
075: /**
076: * Constructor.
077: * @param organisation The organisation which creates the module.
078: * @param name The name of the module.
079: */
080: public ModuleId(String organisation, String name) {
081: if (name == null) {
082: throw new IllegalArgumentException("null name not allowed");
083: }
084: this .organisation = organisation;
085: this .name = name;
086: }
087:
088: /**
089: * Returns the name of the module.
090: * @return The name of the module.
091: */
092: public String getName() {
093: return name;
094: }
095:
096: /**
097: * Returns the name of the organisation.
098: * @return The name of the organisation.
099: */
100: public String getOrganisation() {
101: return organisation;
102: }
103:
104: /** {@inheritDoc} */
105: public boolean equals(Object obj) {
106: if (!(obj instanceof ModuleId)) {
107: return false;
108: }
109: ModuleId other = (ModuleId) obj;
110: if (other.organisation == null) {
111: return organisation == null && other.name.equals(name);
112: } else {
113: return other.organisation.equals(organisation)
114: && other.name.equals(name);
115: }
116: }
117:
118: /** {@inheritDoc} */
119: public int hashCode() {
120: if (hash == 0) {
121: //CheckStyle:MagicNumber| OFF
122: hash = 31;
123: hash = hash
124: * 13
125: + (organisation == null ? 0 : organisation
126: .hashCode());
127: hash = hash * 13 + name.hashCode();
128: //CheckStyle:MagicNumber| ON
129: }
130: return hash;
131: }
132:
133: /** {@inheritDoc} */
134: public String toString() {
135: return organisation + "#" + name;
136: }
137:
138: /** {@inheritDoc} */
139: public int compareTo(Object obj) {
140: ModuleId that = (ModuleId) obj;
141: int result = organisation.compareTo(that.organisation);
142: if (result == 0) {
143: result = name.compareTo(that.name);
144: }
145: return result;
146: }
147:
148: /**
149: * Returns the encoded String representing this ModuleId.
150: * @return The ModuleId encoded as String.
151: */
152: public String encodeToString() {
153: return getOrganisation() + ENCODE_SEPARATOR + getName();
154: }
155:
156: /**
157: * Returns a ModuleId
158: * @param encoded
159: * @return The new ModuleId.
160: * @throws IllegalArgumentException If the given String could not be decoded.
161: */
162: public static ModuleId decode(String encoded) {
163: String[] parts = encoded.split(ENCODE_SEPARATOR);
164: if (parts.length != 2) {
165: throw new IllegalArgumentException(
166: "badly encoded module id: '" + encoded + "'");
167: }
168: return new ModuleId(parts[0], parts[1]);
169: }
170:
171: /**
172: * Pattern to use to matched mid text representation.
173: * @see #parse(String)
174: */
175: public static final Pattern MID_PATTERN = Pattern.compile("("
176: + ModuleRevisionId.STRICT_CHARS_PATTERN + "*)" + "#("
177: + ModuleRevisionId.STRICT_CHARS_PATTERN + "+)");
178:
179: /**
180: * Parses the module id text representation and returns it as a {@link ModuleId} instance.
181: *
182: * @param mid
183: * the module id text representation to parse
184: * @return the ModuleId instance corresponding to the representation
185: * @throws IllegalArgumentException
186: * if the given text representation cannot be parsed
187: */
188: public static ModuleId parse(String mid) {
189: Matcher m = MID_PATTERN.matcher(mid);
190: if (!m.matches()) {
191: throw new IllegalArgumentException(
192: "module text representation do not match expected pattern."
193: + " given mid='" + mid + "' expected form="
194: + MID_PATTERN.pattern());
195: }
196:
197: //CheckStyle:MagicNumber| OFF
198: return newInstance(m.group(1), m.group(2));
199: //CheckStyle:MagicNumber| ON
200: }
201: }
|