1 package net.sf.saxon.functions; 2 import net.sf.saxon.expr.XPathContext; 3 import net.sf.saxon.om.Item; 4 import net.sf.saxon.sort.CodepointCollator; 5 import net.sf.saxon.trans.XPathException; 6 import net.sf.saxon.value.AtomicValue; 7 import net.sf.saxon.value.BooleanValue; 8 import net.sf.saxon.value.StringValue; 9 10 import java.text.CollationElementIterator ; 11 import java.text.RuleBasedCollator ; 12 import java.util.Comparator ; 13 14 15 19 20 public class Contains extends CollatingFunction { 21 22 public static final int CONTAINS = 0; 23 public static final int STARTSWITH = 1; 24 public static final int ENDSWITH = 2; 25 public static final int AFTER = 3; 26 public static final int BEFORE = 4; 27 28 31 32 public Item evaluateItem(XPathContext context) throws XPathException { 33 34 Comparator collator = getCollator(2, context, false); 35 36 AtomicValue arg0 = (AtomicValue)argument[0].evaluateItem(context); 37 if (arg0==null) { 38 arg0 = StringValue.EMPTY_STRING; 39 } 40 41 AtomicValue arg1 = (AtomicValue)argument[1].evaluateItem(context); 42 if (arg1==null) { 43 arg1 = StringValue.EMPTY_STRING; 44 }; 45 46 String s0 = arg0.getStringValue(); 47 String s1 = arg1.getStringValue(); 48 49 if (collator instanceof CodepointCollator) { 50 switch(operation) { 52 case CONTAINS: 53 return BooleanValue.get(s0.indexOf(s1) >= 0); 54 case STARTSWITH: 55 return BooleanValue.get(s0.startsWith(s1)); 56 case ENDSWITH: 57 return BooleanValue.get(s0.endsWith(s1)); 58 case AFTER: 59 int i = s0.indexOf(s1); 60 if (i<0) return StringValue.EMPTY_STRING; 61 return StringValue.makeStringValue(s0.substring(i+s1.length())); 62 case BEFORE: 63 int j = s0.indexOf(s1); 64 if (j<0) return StringValue.EMPTY_STRING; 65 return StringValue.makeStringValue(s0.substring(0, j)); 66 default: 67 throw new UnsupportedOperationException ("Unknown operation " + operation); 68 } 69 } else { 70 71 if (!(collator instanceof RuleBasedCollator )) { 72 dynamicError("The collation for " + getDisplayName(context.getController().getNamePool()) + 73 " must be a RuleBaseCollator", context); 74 return null; 75 } 76 RuleBasedCollator rbc = (RuleBasedCollator )collator; 77 CollationElementIterator iter0 = rbc.getCollationElementIterator(s0); 78 CollationElementIterator iter1 = rbc.getCollationElementIterator(s1); 79 80 switch (operation) { 81 case STARTSWITH: 82 return BooleanValue.get( collationStartsWith(iter0, iter1) ); 83 case CONTAINS: 84 case ENDSWITH: 85 return BooleanValue.get( collationContains(iter0, iter1, null) ); 86 case AFTER: 87 int[] ia = new int[2]; 88 boolean ba = collationContains(iter0, iter1, ia); 89 if (ba) { 90 return StringValue.makeStringValue(s0.substring(ia[1])); 91 } else { 92 return StringValue.EMPTY_STRING; 93 } 94 case BEFORE: 95 int[] ib = new int[2]; 96 boolean bb = collationContains(iter0, iter1, ib); 97 if (bb) { 98 return StringValue.makeStringValue(s0.substring(0, ib[0])); 99 } else { 100 return StringValue.EMPTY_STRING; 101 } 102 default: 103 throw new UnsupportedOperationException ("Unknown operation " + operation); 104 } 105 } 106 } 107 108 114 115 private boolean collationStartsWith(CollationElementIterator s0, 116 CollationElementIterator s1) { 117 while (true) { 118 int e1 = s1.next(); 119 if (e1 == -1) { 120 return true; 121 } 122 int e0 = s0.next(); 123 if (e0 != e1) { 124 return false; 125 } 126 } 127 } 128 129 141 142 private boolean collationContains(CollationElementIterator s0, 143 CollationElementIterator s1, 144 int[] offsets ) { 145 int e1 = s1.next(); 146 if (e1 == -1) { 147 return true; 148 } 149 int e0 = -1; 150 while (true) { 151 while (e0 != e1) { 153 e0 = s0.next(); 154 if (e0 == -1) { 155 return false; 157 } 158 } 159 int start = s0.getOffset(); 161 if (collationStartsWith(s0, s1)) { 162 if (operation == ENDSWITH) { 163 if (s0.next() == -1) { 164 return true; 166 } 167 } else { 169 if (offsets != null) { 170 offsets[0] = start-1; 171 offsets[1] = s0.getOffset(); 172 } 173 return true; 174 } 175 } 176 s0.setOffset(start); 178 179 if (s0.getOffset() != start) { 181 s0.next(); 183 } 184 s1.reset(); 185 e0 = -1; 186 e1 = s1.next(); 187 } 189 } 190 191 192 } 193 194 195 196 | Popular Tags |