Richard S. Hall | 85bafab | 2009-07-13 13:25:46 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
| 19 | |
| 20 | package org.cauldron.bld.obr; |
| 21 | |
| 22 | import java.util.ArrayList; |
| 23 | import java.util.List; |
| 24 | |
| 25 | import org.cauldron.sigil.model.common.LDAPExpr; |
| 26 | import org.cauldron.sigil.model.common.LDAPParseException; |
| 27 | import org.cauldron.sigil.model.common.LDAPParser; |
| 28 | import org.cauldron.sigil.model.common.Not; |
| 29 | import org.cauldron.sigil.model.common.Ops; |
| 30 | import org.cauldron.sigil.model.common.SimpleTerm; |
| 31 | import org.cauldron.sigil.model.common.VersionRange; |
| 32 | import org.osgi.framework.Version; |
| 33 | |
| 34 | class VersionRangeHelper { |
| 35 | |
| 36 | // e.g. (&(version>=1.0.0)(version<=2.0.0)) (&(version>1.0.0)(version<2.0.0)) (&(!(version<1.0.0))(!(version>2.0.0))) (&(!(version<=1.0.0))(!(version>=2.0.0))) (version=1.0.0) (version>=1.0.0) (version<=2.0.0) (version>1.0.0) (version<2.0.0) (!(version>2.0.0)) (!(version<1.0.0)) (!(version>=2.0.0)) (!(version<=1.0.0)) |
| 37 | public static void main(String[] args) throws LDAPParseException { |
| 38 | for ( String arg : args ) { |
| 39 | LDAPExpr expr = LDAPParser.parseExpression(arg.trim()); |
| 40 | System.out.println( expr + " -> " + decodeVersions(expr) ); |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | static VersionRange decodeVersions(LDAPExpr expr) throws NumberFormatException { |
| 45 | ArrayList<LDAPExpr> terms = new ArrayList<LDAPExpr>(1); |
| 46 | |
| 47 | findExpr("version", expr, terms); |
| 48 | |
| 49 | if ( terms.isEmpty() ) { |
| 50 | // woo hoo! |
| 51 | return VersionRange.ANY_VERSION; |
| 52 | } |
| 53 | else { |
| 54 | switch ( terms.size() ) { |
| 55 | case 1: { |
| 56 | return parseSimpleVersionRange(terms.get(0)); |
| 57 | } |
| 58 | case 2: { |
| 59 | return parseCompoundVersionRange(terms.get(0), terms.get(1)); |
| 60 | } |
| 61 | default: { |
| 62 | // (&(version>=min)(!(version=min))(version<=max)(!(version=max))) - (min,max) - not dealt with!! |
| 63 | // (&(|(version>min)(version=min))(|(version<max)(version=max))) - [min,max] - not dealt with!! |
| 64 | throw new NumberFormatException("Failed to parse complicated version expression " + expr); |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | // (&(version>=min)(version<=max)) - [min,max] |
| 71 | // (&(version>min)(version<max)) - (min,max) |
| 72 | // |
| 73 | // (&(!(version<min))(!(version>max))) - [min,max] |
| 74 | // (&(!(version<=min))(!(version>=max)) - (min,max) |
| 75 | private static VersionRange parseCompoundVersionRange(LDAPExpr left, LDAPExpr right) throws NumberFormatException { |
| 76 | VersionRange one = parseSimpleVersionRange(left); |
| 77 | VersionRange two = parseSimpleVersionRange(right); |
| 78 | |
| 79 | // sanity check |
| 80 | if ( one.isPointVersion() || two.isPointVersion() ) { |
| 81 | throw new NumberFormatException("Unexpected point version in compound expression " + left); |
| 82 | } |
| 83 | |
| 84 | VersionRange max = one.getFloor().equals( Version.emptyVersion ) ? one : two; |
| 85 | VersionRange min = max == one ? two : one; |
| 86 | |
| 87 | return new VersionRange( min.isOpenFloor(), min.getFloor(), max.getCeiling(), max.isOpenCeiling() ); |
| 88 | } |
| 89 | |
| 90 | // possible variations |
| 91 | // (version=v) - [v,v] |
| 92 | // |
| 93 | // (version>=min) - [min,*) |
| 94 | // (version<=max) - [0,max] |
| 95 | // |
| 96 | // (version>min) - (min,*) |
| 97 | // (version<max) - [0,max) |
| 98 | // |
| 99 | // (!(version>max)) - [0,max] |
| 100 | // (!(version<min)) - [min,*) |
| 101 | // (!(version>=max)) - [0,max) |
| 102 | // (!(version<=min)) - (0,*) |
| 103 | private static VersionRange parseSimpleVersionRange(LDAPExpr expr) throws NumberFormatException { |
| 104 | Version min = Version.emptyVersion; |
| 105 | Version max = VersionRange.INFINITE_VERSION; |
| 106 | boolean openFloor = false; |
| 107 | boolean openCeiling = false; |
| 108 | if ( expr instanceof Not ) { |
| 109 | Not n = (Not) expr; |
| 110 | SimpleTerm t = (SimpleTerm) n.getEx(); |
| 111 | if ( t.getOp() == Ops.EQ ) { |
| 112 | throw new NumberFormatException("Unexpected point version in negated expression " + expr); |
| 113 | } |
| 114 | if ( !isMax(t.getOp()) ) { |
| 115 | max = toVersion(t); |
| 116 | openCeiling = !openFloor(t); |
| 117 | } |
| 118 | else if ( !isMin(t.getOp()) ) { |
| 119 | min = toVersion(t); |
| 120 | openFloor = !openCeiling(t); |
| 121 | } |
| 122 | else { |
| 123 | throw new IllegalStateException("Unexpected operator " + t.getOp()); |
| 124 | } |
| 125 | } |
| 126 | else { |
| 127 | SimpleTerm t = (SimpleTerm) expr; |
| 128 | if ( t.getOp().equals( Ops.EQ ) ) { |
| 129 | max = toVersion(t); |
| 130 | min = max; |
| 131 | openFloor = false; |
| 132 | openCeiling = false; |
| 133 | } |
| 134 | else if ( isMax(t.getOp()) ) { |
| 135 | max = toVersion(t); |
| 136 | openCeiling = openCeiling(t); |
| 137 | } |
| 138 | else if ( isMin(t.getOp()) ) { |
| 139 | min = toVersion(t); |
| 140 | openFloor = openFloor(t); |
| 141 | } |
| 142 | else { |
| 143 | throw new IllegalStateException("Unexpected operator " + t.getOp()); |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | return new VersionRange( openFloor, min, max, openCeiling ); |
| 148 | } |
| 149 | |
| 150 | private static Version toVersion(SimpleTerm t) { |
| 151 | return new Version(t.getRval()); |
| 152 | } |
| 153 | |
| 154 | private static boolean isMax(Ops op) { |
| 155 | return op == Ops.LE || op == Ops.LT; |
| 156 | } |
| 157 | |
| 158 | private static boolean isMin(Ops op) { |
| 159 | return op == Ops.GE || op == Ops.GT; |
| 160 | } |
| 161 | |
| 162 | private static boolean openFloor(SimpleTerm t) { |
| 163 | return t.getOp() == Ops.GT; |
| 164 | } |
| 165 | |
| 166 | private static boolean openCeiling(SimpleTerm t) { |
| 167 | return t.getOp() == Ops.LT; |
| 168 | } |
| 169 | |
| 170 | private static void findExpr(String string, LDAPExpr expr, List<LDAPExpr> terms) { |
| 171 | if ( expr instanceof SimpleTerm ) { |
| 172 | SimpleTerm term = (SimpleTerm) expr; |
| 173 | if ( term.getName().equals(string) ) { |
| 174 | terms.add(term); |
| 175 | } |
| 176 | } |
| 177 | else if ( expr instanceof Not ) { |
| 178 | Not not = (Not) expr; |
| 179 | if ( not.getEx() instanceof SimpleTerm ) { |
| 180 | SimpleTerm term = (SimpleTerm) not.getEx(); |
| 181 | if ( term.getName().equals(string) ) { |
| 182 | terms.add(not); |
| 183 | } |
| 184 | } |
| 185 | } |
| 186 | else { |
| 187 | for ( LDAPExpr c : expr.getChildren() ) { |
| 188 | findExpr(string, c, terms); |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | } |