blob: 50b0fb15e6058c25ac7c1b35ed3228f9d8280b12 [file] [log] [blame]
Richard S. Hall85bafab2009-07-13 13:25:46 +00001/*
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
20package org.cauldron.bld.obr;
21
22import java.util.ArrayList;
23import java.util.List;
24
25import org.cauldron.sigil.model.common.LDAPExpr;
26import org.cauldron.sigil.model.common.LDAPParseException;
27import org.cauldron.sigil.model.common.LDAPParser;
28import org.cauldron.sigil.model.common.Not;
29import org.cauldron.sigil.model.common.Ops;
30import org.cauldron.sigil.model.common.SimpleTerm;
31import org.cauldron.sigil.model.common.VersionRange;
32import org.osgi.framework.Version;
33
34class 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}