1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package cc
.squirreljme
.plugin
.swm
;
12 import cc
.squirreljme
.plugin
.util
.NaturalComparator
;
13 import cc
.squirreljme
.plugin
.util
.StringUtils
;
14 import java
.lang
.ref
.Reference
;
15 import java
.lang
.ref
.WeakReference
;
16 import java
.util
.Objects
;
19 * This represents a dependency that a LIBlet or MIDlet may depend on.
23 public final class SuiteDependency
24 implements Comparable
<SuiteDependency
>, MarkedDependency
26 /** The dependency type. */
27 protected final SuiteDependencyType type
;
29 /** The dependency level. */
30 protected final SuiteDependencyLevel level
;
33 protected final SuiteName name
;
36 protected final SuiteVendor vendor
;
38 /** The version range. */
39 protected final SuiteVersionRange version
;
41 /** String representation. */
42 private Reference
<String
> _string
;
45 * Initializes the dependency which is parsed from the given input string.
47 * @param __s The string to parse.
48 * @throws InvalidSuiteException If the string is not valid.
49 * @throws NullPointerException On null arguments.
52 public SuiteDependency(String __s
)
53 throws InvalidSuiteException
, NullPointerException
57 throw new NullPointerException("NARG");
62 // Extract all semicolon positions
63 int[] sc
= StringUtils
.multipleIndexOf(';', __s
);
65 /* {@squirreljme.error DG06 Expected four semi-colons in the
66 dependency field. (The input dependency)} */
68 throw new InvalidSuiteException(String
.format(
72 String intype
= __s
.substring(0, sc
[0]).trim(),
73 inlevel
= __s
.substring(sc
[0] + 1, sc
[1]).trim(),
74 inname
= __s
.substring(sc
[1] + 1, sc
[2]).trim(),
75 invendor
= __s
.substring(sc
[2] + 1, sc
[3]).trim(),
76 inversion
= __s
.substring(sc
[3] + 1).trim();
79 SuiteDependencyType type
;
80 this.type
= (type
= SuiteDependencyType
.of(intype
));
81 this.level
= SuiteDependencyLevel
.of(inlevel
);
86 SuiteVersionRange version
;
87 this.name
= (name
= (inname
.isEmpty() ?
null :
88 new SuiteName(inname
)));
89 this.vendor
= (vendor
= (invendor
.isEmpty() ?
null :
90 new SuiteVendor(invendor
)));
91 this.version
= (version
= (inversion
.isEmpty() ?
null :
92 new SuiteVersionRange(inversion
)));
95 SuiteDependency
.__check(type
, this.level
, name
, vendor
, version
);
99 * Initializes the depedency with the given type, level, and where the
100 * remainder of the dependencies are parsed from the specified string.
102 * @param __type The type of dependency this is.
103 * @param __level The level of the dependency.
104 * @param __s The string to decode for the remainder of the dependency.
105 * @throws InvalidSuiteException If the input parameters are not valid.
106 * @throws NullPointerException On null arguments.
109 public SuiteDependency(SuiteDependencyType __type
,
110 SuiteDependencyLevel __level
, String __s
)
111 throws InvalidSuiteException
, NullPointerException
113 if (__type
== null || __level
== null || __s
== null)
114 throw new NullPointerException("NARG");
119 // Extract all semicolon positions
120 int[] sc
= StringUtils
.multipleIndexOf(';', __s
);
122 /* {@squirreljme.error DG07 Expected two semi-colons in the
123 dependency field. (The input dependency)} */
125 throw new InvalidSuiteException(String
.format(
129 String inname
= __s
.substring(0, sc
[0]).trim(),
130 invendor
= __s
.substring(sc
[0] + 1, sc
[1]).trim(),
131 inversion
= __s
.substring(sc
[1] + 1).trim();
133 // Parse areas fields
136 SuiteVersionRange version
;
137 this.name
= (name
= (inname
.isEmpty() ?
null :
138 new SuiteName(inname
)));
139 this.vendor
= (vendor
= (invendor
.isEmpty() ?
null :
140 new SuiteVendor(invendor
)));
141 this.version
= (version
= (inversion
.isEmpty() ?
null :
142 new SuiteVersionRange(inversion
)));
144 SuiteDependency
.__check(__type
, __level
, name
, vendor
, version
);
148 this.level
= __level
;
152 * Initializes the dependency using the given parameters.
154 * @param __type The type of dependency this is.
155 * @param __level The level of the dependency.
156 * @param __name The name.
157 * @param __vendor The vendor.
158 * @param __version The version.
159 * @throws InvalidSuiteException If the input parameters are not valid.
160 * @throws NullPointerException If no type and/or name were specified.
163 public SuiteDependency(SuiteDependencyType __type
,
164 SuiteDependencyLevel __level
, SuiteName __name
,
165 SuiteVendor __vendor
, SuiteVersionRange __version
)
166 throws InvalidSuiteException
, NullPointerException
168 if (__type
== null || __level
== null)
169 throw new NullPointerException("NARG");
171 SuiteDependency
.__check(__type
, __level
, __name
, __vendor
, __version
);
175 this.level
= __level
;
177 this.vendor
= __vendor
;
178 this.version
= __version
;
186 public final int compareTo(SuiteDependency __d
)
187 throws NullPointerException
190 throw new NullPointerException("NARG");
193 int rv
= this.type
.compareTo(__d
.type
);
198 rv
= this.level
.compareTo(__d
.level
);
203 rv
= Objects
.<SuiteName
>compare(this.name
, __d
.name
,
204 NaturalComparator
.<SuiteName
>instance());
209 rv
= Objects
.<SuiteVendor
>compare(this.vendor
, __d
.vendor
,
210 NaturalComparator
.<SuiteVendor
>instance());
215 return Objects
.<SuiteVersionRange
>compare(this.version
, __d
.version
,
216 NaturalComparator
.<SuiteVersionRange
>instance());
224 public boolean equals(Object __o
)
230 if (!(__o
instanceof SuiteDependency
))
234 SuiteDependency o
= (SuiteDependency
)__o
;
235 return this.type
.equals(o
.type
) &&
236 this.level
.equals(o
.level
) &&
237 Objects
.equals(this.name
, o
.name
) &&
238 Objects
.equals(this.vendor
, o
.vendor
) &&
239 Objects
.equals(this.version
, o
.version
);
247 public int hashCode()
249 return this.type
.hashCode() ^
250 this.level
.hashCode() ^
251 Objects
.hashCode(this.name
) ^
252 Objects
.hashCode(this.vendor
) ^
253 Objects
.hashCode(this.version
);
261 public boolean isOptional()
263 return this.level
.isOptional();
267 * Is this a required dependency?
269 * @return {@code true} if this is a required dependency.
272 public boolean isRequired()
274 return this.level
.isRequired();
278 * Returns the dependency level.
280 * @return The dependency level.
283 public SuiteDependencyLevel
level()
289 * Returns the dependency name.
291 * @return The dependency name, may be {@code null}.
294 public SuiteName
name()
304 public boolean matchesProvided(MarkedProvided __mp
)
305 throws NullPointerException
308 throw new NullPointerException("NARG");
310 SuiteDependencyType type
= this.type
;
311 Class
<?
> mpclass
= __mp
.getClass();
312 SuiteName name
= this.name
;
313 SuiteVendor vendor
= this.vendor
;
314 SuiteVersionRange version
= this.version
;
321 // Potential internal project name
322 if (__mp
instanceof InternalName
)
324 String myname
= name
.toString();
328 if ((dxat
= myname
.indexOf('@')) < 0)
331 // Prefix must be project reference
332 if (!myname
.substring(0, dxat
).
333 equals("squirreljme.project"))
336 // Otherwise the project name must match
337 return myname
.substring(dxat
+ 1).
338 equals(((InternalName
)__mp
).name());
346 // Typed suite information
347 if (__mp
instanceof TypedSuite
)
349 TypedSuite other
= (TypedSuite
)__mp
;
350 SuiteIdentifier ident
= other
.suite();
352 // Only match other libraries
353 if (other
.type() != JavaMEMidletType
.LIBRARY
)
357 if (!name
.equals(ident
.name()))
360 // Match vendor if specified
362 if (!vendor
.equals(ident
.vendor()))
365 // Check if version in range if specified
367 if (!version
.inRange(ident
.version()))
380 if (__mp
instanceof JavaMEStandard
)
382 JavaMEStandard other
= (JavaMEStandard
)__mp
;
385 if (!name
.equals(other
.name()))
388 // Match vendor if specified
390 if (!vendor
.equals(other
.vendor()))
393 // Check if version in range if specified
395 if (!version
.inRange(other
.version()))
406 /* {@squirreljme.error DG08 Illegal dependency check.
407 (The dependency type; The target class)} */
409 throw new RuntimeException(String
.format("AR08 %s %s",
415 * Returns a dependency which is the same as this one except that it is
418 * @return This dependency but required.
421 public SuiteDependency
toRequired()
423 if (this.isRequired())
425 return new SuiteDependency(this.type
, SuiteDependencyLevel
.REQUIRED
,
426 this.name
, this.vendor
, this.version
);
430 * Returns a dependency which is the same as this one except that it is
433 * @return This dependency but optional.
436 public SuiteDependency
toOptional()
438 if (this.isOptional())
440 return new SuiteDependency(this.type
, SuiteDependencyLevel
.OPTIONAL
,
441 this.name
, this.vendor
, this.version
);
449 public String
toString()
452 Reference
<String
> ref
= this._string
;
456 if (ref
== null || null == (rv
= ref
.get()))
458 // These are optional
459 SuiteName name
= this.name
;
460 SuiteVendor vendor
= this.vendor
;
461 SuiteVersionRange version
= this.version
;
464 this._string
= new WeakReference
<>((rv
= String
.format(
465 "%s;%s;%s;%s;%s", this.type
, this.level
,
466 (name
== null ?
"" : name
),
467 (vendor
== null ?
"" : vendor
),
468 (version
== null ?
"" : version
))));
476 * Returns the dependency type.
478 * @return The dependency type.
481 public SuiteDependencyType
type()
487 * Returns the dependency vendor.
489 * @return The dependency vendor, may be {@code null}.
492 public SuiteVendor
vendor()
498 * Returns the dependency version.
500 * @return The dependency version, may be {@code null}.
503 public SuiteVersionRange
version()
509 * Checks whether the provided parameters are correct.
511 * @param __type The type of dependency this is.
512 * @param __level The level of the dependency.
513 * @param __name The name.
514 * @param __vendor The vendor.
515 * @param __version The version.
516 * @throws InvalidSuiteException If the input parameters are not valid.
519 private static void __check(SuiteDependencyType __type
,
520 SuiteDependencyLevel __level
, SuiteName __name
,
521 SuiteVendor __vendor
, SuiteVersionRange __version
)
522 throws InvalidSuiteException
524 /* {@squirreljme.error DG09 Dependencies on LIBlets must have the
525 name, vendor, and version set. (The type; The level; The name;
526 The vendor; The version)} */
527 if (__type
== SuiteDependencyType
.LIBLET
&& (__name
== null ||
528 __vendor
== null || __version
== null))
529 throw new InvalidSuiteException(
530 String
.format("AR09 %s %s %s %s %s", __type
, __level
, __name
,
531 __vendor
, __version
));