OK, I have implemented and attached a Version class with the desired behavior and tested that the following works as expected

   System.out.println("toString:" + new Version("5.0.3", "*"));
   System.out.println("hashCode:" + new Version("5.0.3", "*").hashCode());
System.out.println("not equals:" + new Version("5.0.3", "*").equals(new Version("5", "*"))); System.out.println("compareTo == 0:" + new Version("5.0.3", "*").compareTo(new Version("5", "*"))); System.out.println("compareTo == +:" + new Version("5.0.3", "*").compareTo(new Version("5", "0"))); System.out.println("compareTo == -:" + new Version("5.0.3", "*").compareTo(new Version("5.0.4", "*")));

Given the way that compareTo works, I changed the wildcard behavior from what is listed before to make the wildcard behavior only affect compareTo() results of 0. However, this still has the desired effect because min- and max- comparisons are <= and >= respectively. Anway, I believe looking at the code in compareTo() will give everyone a better idea of what I intend.

Note also that I am unsure what package this should be in. I placed it in the trinidad api context class simply because that is where the Triniad Agent is and I would eventually expect this Object to be returned by the Agent.

-- Blake Sullivan


Blake Sullivan said the following On 4/18/2008 3:15 PM PT:
OK, how about

option 5) the version feature is a String that matches the native "major.minor.whatever" format of the browser's engine. If the browser's engine uses non "." for separating versions, "." is used instead.

For matches, the "*" character is allowed in any version section.
For comparisons, the "*" is always a valid match regardless of <, >, or = comparison

For comparisons where the comparison side contains fewer version sections than the actual browser version, the comparison side is padded with * version sections and the comparison occurs as above.

For comparisons where the comparison side contains more version sections than the actual browser version, the browser version is padded with 0 version sections and the comparison occurs as above.

// user wants to match IE 5, actual browser version ie 5.5
@agent ie and (version:5)

matches because version:5 expands to version 5.* and 5.* matches 5.5

@agent ie and (min-version:5)

matches because version:5 expands to version 5.* and 5.*  < 5.5 = true

@agent ie and (max-version:5)

matches because version:5 expands to version 5.* and 5.* > 5.5 = true

// actual browser version gecko 1.9
@agent gecko and (min-version:1.9.2)

does not match because the browser version 1.9 expands to 1.9.0 and 1.9.2 is > than 1.9.0

// actual browser version gecko 1.9
@agent gecko and (min-version:1.9.*)

matches because the browser version 1.9 expands to 1.9.0 and 1.9.* == 1.9.0

-- Blake Sullivan





Blake Sullivan said the following On 4/17/2008 12:31 PM PT:
If we agree that we like the we like the media query syntax and that the only issue is how to handle less than (as opposed the <=) for the max-version, then we can just collect up the proposals and pick one:

1) The verbose and explicit  (max-version-less-than:8).
2) Define that for the version feature, max-version means < not <=. Inconsistent with other uses of max (max-version:8) 3) Let the skinning author provide enough precision to avoid the need to distinguish between < 8 and <= a number that apporaches 8 (max-version:7.99)
4) Add an operator suffix (max-version-lt:8)

1) is gross
2) is potentially confusing due to inconsistency
3) might not be immediately obvious and could theoretically have precision problems
4) is not immediately obvious either but incredibly flexible

I vote for 3) since it gets the job done and doesn't preclude doing more later.

-- Blake Sullivan




Andrew Robinson said the following On 4/17/2008 11:53 AM PT:
http://www.w3.org/TR/REC-CSS2/media.html

@import url("loudvoice.css") aural;

so here are multiple groups of characters that show that spaces are
acceptable (import url and aural keywords in one "bunch")

url("loudvoice.css")
shows that parenthesis with at least one argument is acceptable

@media screen, print {
Shown that a comma separated list, unlike normal CSS selectors applies
to the whole @ (meaning that it wasn't "@meda screen, @media print")

From css3 (http://www.w3.org/TR/css3-reader/):
@import "my-print-style.css" print;
here, a quoted string is permissible (goes with the url values in CSS rules)

<?xml-stylesheet href="style1.css" type="text/css"
  media="screen and (color) and (max-width: 400px"?>
<?xml-stylesheet href="style2.css" type="text/css"
  media="reader and (max-device-ratio: 1/1)"?>
Hmmm.... interesting, but do we want to reuse something that relates
to CSS but is not in a CSS file?

@media reader and (grid: 0)
Ah, now we are talking. This looks like what Blake was referring to

From http://www.css3.info/preview/media-queries/:
@media all and (min-width: 640px) {
Even better, showing an "all" keyword and having "normal CSS
properties" in parens.

http://www.css3.info/preview/attribute-selectors/:
Do we dare take RegExp like syntax from attr. selectors and apply them
to @agent rules?


So I can see Blake's suggestion being backed by these, but IMO
"max-version-less-than:8" is too long to remember.

Perhaps just:
IE 5.5 or greater:
@agent ie and (min-version: 5.5)

IE 5.0 or greater:
@agent ie and (min-version: 5)

IE >= 5.0 and < 6.0:
@agent ie and (version: 5)
or (I like this one less):
@agent ie and (major-version: 5)

IE <= 6.0:
@agent ie and (max-version: 6)

IE < 6:
@agent ie and (max-version: 5.9)

IE >= 6.0 and < 8.0:
@agent ie and (min-version: 6) and (max-version: 7.9)
same as:
@agent ie and (min-version: 6) and (max-version: 7)

IE >= 6.0 and <= 8.0:
@agent ie and (min-version: 6) and (max-version: 8.0)

IE >= 6.0 and <= 8.x:
@agent ie and (min-version: 6) and (max-version: 8)

So x.y (ie 5.5) means precisely that, no vagueness and x (ie 6) means
major version x regardless of minor version. If it is too hard to
parse the decimal and remember it, "max-major-version",
"min-major-version" and "major-version" could be used for integer only
comparison with the major version and "max-version", "min-version" and
"version" could be used for full major.minor comparison.

I think using something like 7.9 or  7.99 could theoretically be used
for less than but not equal to. I think the fewer number of keywords
the clearer it will be to use. Just my opinion.

Just adding some thoughts to chew on since concrete ideas were asked for.

-Andrew


On Thu, Apr 17, 2008 at 12:26 PM, Cristi Toth <[EMAIL PROTECTED]> wrote:
Hi guys,

You're right, I should have discussed the format before committing it.
I started fixing the issue using the format that was specified there...
(there weren't to many comments on that issue btw...)
During I was fixing it, I noticed that XSS suppported multiple versions,
so I adapted what was suggested on the issue to support that too.

Anyway, lets get this subject out in a new thread
and stick here to discussing the format.

Guys, those of you that suggested some general guidelines, they all sound
good,
but please try to think of some concrete format that comply with those
guidelines.

If we decide a final format and implement it until its get released, then no
big harm done.
 So please be constructive ;)

Thanks for any feedback!

cheers,
--

Cristi Toth

-------------
Codebeat
www.codebeat.ro





/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.apache.myfaces.trinidad.context;

import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * Immutable Representation of a dot-separated version.
 * 
 * This representation
 * allows individual sections of the version to be wild-carded and allows
 * for comparisons between Versions with different numbers of version
 * subsections to be compared.  When comparing Versions, each version
 * subsection is compared from left to right.  If one Version doesn't have
 * a version subsection at the current index, the value of versionPadding
 * is used for this comparison.  Version subsections with the wild-card value 
"*"
 * care considered equal.  The value returned by compareTo() is the value of the
 * first non-equal version subsection or zero if all subsections match.
 * 
 * Due to the support for wild-cards, this class has a natural ordering
 * that is inconsistent with equals.  For example,
 * <code>Version("5", "*").compareTo(Version("5.0", "*") == 0</code>
 * <code>Version("5", "*").equals(Version("5.0", "*") == false;</code>
 * @author Blake Sullivan
 */
public final class Version implements Comparable<Version>
{
  /**
   * Creates a Version instance from the dot-separated Version String and the
   * versionPadding.
   * @param version The dot-separated version to represent
   * @param versionPadding The value to return for sub-version sections
   * requested beyond the sub-version sections present in the version String
   * @throws NullPointerException if version or versionPadding are null
   * @throws IllegalArgumentException if version or versionPadding are the
   * empty String
   */
  public Version(String version, String versionPadding)
  {
    _checkNonEmptyString(version, "version");
    _checkNonEmptyString(version, "versionPadding");
    
    // build the array of subversions
    _versions = _DOT_SPLITTER.split(version, 0);    
    _versionPadding = versionPadding;
    
    // sicne we're immutable, we might as well calculate this up front
    // while we still have the String version around
    _hashCode = version.hashCode() * 37 + versionPadding.hashCode();
  }

  /**
   * When comparing Versions, each version
   * subsection is compared from left to right.  If one Version doesn't have
   * a version subsection at the current index, the value of versionPadding
   * is used for this comparison.  Version subsections with the wild-card value 
"*"
   * care considered equal.  The value returned by compareTo() is the value of 
the
   * first non-equal version subsection or zero if all subsections match.
   * @param otherVersion The Version object to compare this Version Object with
   * @return a negative integer, zero, or a positive integer as this object
   *            is less than, equal to, or greater than the specified object.
   */
  public int compareTo(Version otherVersion)
  {
    int ourVersionCount = _versions.length;
    int otherVersionCount = otherVersion._versions.length;
    
    int compareCount = (ourVersionCount > otherVersionCount)
                         ? ourVersionCount
                         : otherVersionCount;
    
    for (int versionIndex = 0; versionIndex < compareCount; versionIndex++)
    {
      String ourSubVersion = _getSubVersion(versionIndex);
      String otherSubVersion = otherVersion._getSubVersion(versionIndex);
      
      // treat "*" wildcard as equals
      if ("*".equals(ourSubVersion) || "*".equals(otherSubVersion))
      {
        continue;
      }
      else
      {
        // compare the sub-result
        int result = ourSubVersion.compareTo(otherSubVersion);
        
        // not equal, so return the result
        if (result != 0)
          return result;
      }
    }
    
    // equivalent
    return 0;
  }
  @Override
  public String toString()
  {
    // rebuild the initial version string from the split array
    StringBuilder versionBuilder = new StringBuilder();
    int versionCount = _versions.length;
    
    for (int i = 0;;)
    {
      versionBuilder.append(_versions[i]);
      
      i++;
      
      if (i != versionCount)
        versionBuilder.append('.');
      else
        break;
    }
        
    return versionBuilder.toString();    
  }
  
  @Override
  public boolean equals(Object o)
  {
    if (o == this)
      return true;
    else if (!(o instanceof Version))
      return false;
    else
    {
      Version otherVersion = (Version)o;
      
      // we are equal if all of version content and padding are equal
      return _versionPadding.equals(otherVersion._versionPadding) &&
             Arrays.equals(_versions, otherVersion._versions);
    }
  }
  
  @Override
  public int hashCode()
  {
    // used cached version
    return _hashCode;
  }
  
  /**
   * Returns the contents of the sub-version section of the overall version,
   * padding the result with the version padding if the version section
   * index is greater than the number of actual version sections in this
   * version
   * @param versionIndex index of the "." version section from the left side
   * of the version string.
   * @return The content of the version section if available, otehrwise the
   * versionPadding
   */
  private String _getSubVersion(int versionIndex)
  {
    if (versionIndex >= _versions.length)
      return _versionPadding;
    else
      return _versions[versionIndex];
  }

  
  private void _checkNonEmptyString(String checkedString, String identifier)
  {
    if (checkedString == null)
      throw new NullPointerException(identifier + " must be non-null");
    
    if (checkedString.length() == 0)
      throw new IllegalArgumentException(identifier + " must be non-empty");
  }
  
  private final String[] _versions;
  private final String _versionPadding;
  private final int _hashCode;
  
  // cache the compiled splitter
  private static final Pattern _DOT_SPLITTER = Pattern.compile("\\.");
}

Reply via email to