sbTextPropertyInfo.cpp
Go to the documentation of this file.
1 /*
2  *=BEGIN SONGBIRD GPL
3  *
4  * This file is part of the Songbird web player.
5  *
6  * Copyright(c) 2005-2010 POTI, Inc.
7  * http://www.songbirdnest.com
8  *
9  * This file may be licensed under the terms of of the
10  * GNU General Public License Version 2 (the ``GPL'').
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the GPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the GPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/gpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  *=END SONGBIRD GPL
23  */
24 
25 #include "sbTextPropertyInfo.h"
26 
27 #include <nsAutoPtr.h>
28 #include <nsComponentManagerUtils.h>
29 #include <nsUnicharUtils.h>
30 #include <nsMemory.h>
31 
32 #include <sbIStringTransform.h>
33 
34 #include <sbLockUtils.h>
35 #include <sbStringUtils.h>
36 
37 #include <locale> // for collation
38 #include <prmem.h>
39 #include <errno.h>
40 
43 
44 NS_INTERFACE_TABLE_HEAD(sbTextPropertyInfo)
45 NS_INTERFACE_TABLE_BEGIN
46 NS_INTERFACE_TABLE_ENTRY(sbTextPropertyInfo, sbITextPropertyInfo)
47 NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(sbTextPropertyInfo, sbIPropertyInfo, sbITextPropertyInfo)
48 NS_INTERFACE_TABLE_END
49 NS_INTERFACE_TABLE_TAIL_INHERITING(sbPropertyInfo)
50 
51 sbTextPropertyInfo::sbTextPropertyInfo()
52 : mMinMaxLock(nsnull)
53 , mMinLen(0)
54 , mMaxLen(0)
55 , mEnforceLowercaseLock(nsnull)
56 , mEnforceLowercase(PR_FALSE)
57 , mNoCompressWhitespaceLock(nsnull)
58 , mNoCompressWhitespace(PR_FALSE)
59 {
60  mType = NS_LITERAL_STRING("text");
61 
62  mMinMaxLock = PR_NewLock();
63  NS_ASSERTION(mMinMaxLock,
64  "sbTextPropertyInfo::mMinMaxLock failed to create lock!");
65 
66  mEnforceLowercaseLock = PR_NewLock();
67  NS_ASSERTION(mEnforceLowercaseLock,
68  "sbTextPropertyInfo::mEnforceLowercaseLock failed to create lock!");
69 
70  mNoCompressWhitespaceLock = PR_NewLock();
71  NS_ASSERTION(mNoCompressWhitespaceLock,
72  "sbTextPropertyInfo::mNoCompressWhitespaceLock failed to create lock!");
73 }
74 
76 {
77  if(mMinMaxLock) {
78  PR_DestroyLock(mMinMaxLock);
79  }
80 
82  PR_DestroyLock(mEnforceLowercaseLock);
83  }
84 
86  PR_DestroyLock(mNoCompressWhitespaceLock);
87  }
88 }
89 
90 nsresult
92 {
93  nsresult rv;
94 
95  rv = sbPropertyInfo::Init();
96  NS_ENSURE_SUCCESS(rv, rv);
97 
98  rv = InitializeOperators();
99  NS_ENSURE_SUCCESS(rv, rv);
100 
101  return NS_OK;
102 }
103 
104 nsresult
106 {
107  nsresult rv;
108  nsAutoString op;
109  nsRefPtr<sbPropertyOperator> propOp;
110 
111  rv = sbPropertyInfo::GetOPERATOR_CONTAINS(op);
112  NS_ENSURE_SUCCESS(rv, rv);
113  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.contains"));
114  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
115  rv = mOperators.AppendObject(propOp);
116  NS_ENSURE_SUCCESS(rv, rv);
117 
118  rv = sbPropertyInfo::GetOPERATOR_NOTCONTAINS(op);
119  NS_ENSURE_SUCCESS(rv, rv);
120  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.not_contain"));
121  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
122  rv = mOperators.AppendObject(propOp);
123  NS_ENSURE_SUCCESS(rv, rv);
124 
125  rv = sbPropertyInfo::GetOPERATOR_EQUALS(op);
126  NS_ENSURE_SUCCESS(rv, rv);
127  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.is"));
128  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
129  rv = mOperators.AppendObject(propOp);
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  rv = sbPropertyInfo::GetOPERATOR_NOTEQUALS(op);
133  NS_ENSURE_SUCCESS(rv, rv);
134  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.is_not"));
135  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
136  rv = mOperators.AppendObject(propOp);
137  NS_ENSURE_SUCCESS(rv, rv);
138 
139  rv = sbPropertyInfo::GetOPERATOR_BEGINSWITH(op);
140  NS_ENSURE_SUCCESS(rv, rv);
141  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.starts"));
142  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
143  rv = mOperators.AppendObject(propOp);
144  NS_ENSURE_SUCCESS(rv, rv);
145 
146  rv = sbPropertyInfo::GetOPERATOR_NOTBEGINSWITH(op);
147  NS_ENSURE_SUCCESS(rv, rv);
148  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.not_start"));
149  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
150  rv = mOperators.AppendObject(propOp);
151  NS_ENSURE_SUCCESS(rv, rv);
152 
153  rv = sbPropertyInfo::GetOPERATOR_ENDSWITH(op);
154  NS_ENSURE_SUCCESS(rv, rv);
155  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.ends"));
156  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
157  rv = mOperators.AppendObject(propOp);
158  NS_ENSURE_SUCCESS(rv, rv);
159 
160  rv = sbPropertyInfo::GetOPERATOR_NOTENDSWITH(op);
161  NS_ENSURE_SUCCESS(rv, rv);
162  propOp = new sbPropertyOperator(op, NS_LITERAL_STRING("&smart.text.not_end"));
163  NS_ENSURE_TRUE(propOp, NS_ERROR_OUT_OF_MEMORY);
164  rv = mOperators.AppendObject(propOp);
165  NS_ENSURE_SUCCESS(rv, rv);
166 
167  return NS_OK;
168 }
169 
170 NS_IMETHODIMP sbTextPropertyInfo::Validate(const nsAString & aValue, PRBool *_retval)
171 {
172  NS_ENSURE_ARG_POINTER(_retval);
173 
174  PRUint32 len = aValue.Length();
176 
177  *_retval = PR_TRUE;
178 
179  if(mMinLen && len < mMinLen) {
180  *_retval = PR_FALSE;
181  }
182 
183  if(mMaxLen && len > mMaxLen) {
184  *_retval = PR_FALSE;
185  }
186 
187  return NS_OK;
188 }
189 
190 NS_IMETHODIMP sbTextPropertyInfo::Sanitize(const nsAString & aValue, nsAString & _retval)
191 {
192  return NS_ERROR_NOT_IMPLEMENTED;
193 }
194 
195 NS_IMETHODIMP sbTextPropertyInfo::Format(const nsAString & aValue, nsAString & _retval)
196 {
197  nsresult rv;
198  PRBool valid = PR_FALSE;
199  PRBool isTrim = PR_FALSE;
200 
201  _retval = aValue;
202 
203  //Don't compress/strip the leading whitespace if requested
204  {
206  if (!mNoCompressWhitespace) {
207  isTrim = PR_TRUE;
208  }
209  }
210  SB_CompressWhitespace(_retval, isTrim, PR_TRUE);
211 
212  PRUint32 len = aValue.Length();
213 
214  {
216 
217  // If a minimum length is specified and is not respected there's nothing
218  // we can do about it, so we reject it.
219  if(mMinLen && len < mMinLen) {
220  _retval = EmptyString();
221  return NS_ERROR_INVALID_ARG;
222  }
223 
224  // If a maximum length is specified and we exceed it, we cut the string to the
225  // maximum length.
226  if(mMaxLen && len > mMaxLen) {
227  _retval.SetLength(mMaxLen);
228  }
229  }
230 
231  // Enforce lowercase if that is requested.
232  {
234  if(mEnforceLowercase) {
235  ToLowerCase(_retval);
236  }
237  }
238 
239  rv = Validate(_retval, &valid);
240  NS_ENSURE_SUCCESS(rv, rv);
241 
242  if(!valid) {
243  rv = NS_ERROR_FAILURE;
244  _retval = EmptyString();
245  }
246 
247  return rv;
248 }
249 
250 // text property info needs to compute local-specific collation data instead
251 // of relying on the ancestor's default implementation (which just calls
252 // MakeSearchable), so that proper sort order are achieved.
253 NS_IMETHODIMP sbTextPropertyInfo::MakeSortable(const nsAString & aValue, nsAString & _retval)
254 {
255  // first compress whitespaces
256  nsAutoString val;
257  val = aValue;
258  CompressWhitespace(val);
259  ToLowerCase(val);
260 
261  nsresult rv;
262 
263  nsCOMPtr<sbIStringTransform> stringTransform =
264  do_CreateInstance(SB_STRINGTRANSFORM_CONTRACTID, &rv);
265  NS_ENSURE_SUCCESS(rv, rv);
266 
267  nsString outVal;
268 
269  // lone> note that if we ever decide to remove the non-alphanum chars from
270  // more than the leading part of the string, we must still not remove those
271  // chars from the entire string. Ie, we can only extend the filtering to the
272  // trailing part of the string, but not the whole string. the reason for this
273  // is that we do not want to remove the "," in "Beatles, The", or it will not
274  // be recognized by the articles removal code since the pattern is "*, The".
275  rv = stringTransform->
276  NormalizeString(EmptyString(),
280  val,
281  outVal);
282  NS_ENSURE_SUCCESS(rv, rv);
283 
284  // don't allow normalization to produce an empty sortable string
285  if (!outVal.IsEmpty()) {
286  val = outVal;
287  }
288 
289  rv = stringTransform->RemoveArticles(val, EmptyString(), outVal);
290  NS_ENSURE_SUCCESS(rv, rv);
291 
292  _retval = outVal;
293 
294  // all done
295  return NS_OK;
296 }
297 
298 NS_IMETHODIMP sbTextPropertyInfo::MakeSearchable(const nsAString & aValue, nsAString & _retval)
299 {
300  nsresult rv;
301  PRBool valid = PR_FALSE;
302 
303  _retval = aValue;
304  CompressWhitespace(_retval);
305  ToLowerCase(_retval);
306 
307  nsCOMPtr<sbIStringTransform> stringTransform =
308  do_CreateInstance(SB_STRINGTRANSFORM_CONTRACTID, &rv);
309  NS_ENSURE_SUCCESS(rv, rv);
310 
311  nsString outVal;
312  rv = stringTransform->NormalizeString(EmptyString(),
314  _retval, outVal);
315  NS_ENSURE_SUCCESS(rv, rv);
316 
317  _retval = outVal;
318 
319  PRUint32 len = aValue.Length();
320 
321  PR_Lock(mMinMaxLock);
322 
323  // If a minimum length is specified and is not respected there's nothing
324  // we can do about it, so we reject it.
325  if(mMinLen && len < mMinLen) {
326  PR_Unlock(mMinMaxLock);
327  _retval = EmptyString();
328  return NS_ERROR_INVALID_ARG;
329  }
330 
331  // If a maximum length is specified and we exceed it, we cut the string to the
332  // maximum length.
333  if(mMaxLen && len > mMaxLen) {
334  _retval.SetLength(mMaxLen);
335  }
336 
337  PR_Unlock(mMinMaxLock);
338 
339  rv = Validate(_retval, &valid);
340  if(!valid) {
341  rv = NS_ERROR_FAILURE;
342  _retval = EmptyString();
343  }
344 
345  return rv;
346 }
347 
348 NS_IMETHODIMP sbTextPropertyInfo::GetMinLength(PRUint32 *aMinLength)
349 {
350  NS_ENSURE_ARG_POINTER(aMinLength);
352  *aMinLength = mMinLen;
353  return NS_OK;
354 }
355 NS_IMETHODIMP sbTextPropertyInfo::SetMinLength(PRUint32 aMinLength)
356 {
358  mMinLen = aMinLength;
359  return NS_OK;
360 }
361 
362 NS_IMETHODIMP sbTextPropertyInfo::GetMaxLength(PRUint32 *aMaxLength)
363 {
364  NS_ENSURE_ARG_POINTER(aMaxLength);
366  *aMaxLength = mMaxLen;
367  return NS_OK;
368 }
369 NS_IMETHODIMP sbTextPropertyInfo::SetMaxLength(PRUint32 aMaxLength)
370 {
372  mMaxLen = aMaxLength;
373  return NS_OK;
374 }
375 
376 NS_IMETHODIMP sbTextPropertyInfo::GetEnforceLowercase(PRBool *aEnforceLowercase)
377 {
378  NS_ENSURE_ARG_POINTER(aEnforceLowercase);
380  *aEnforceLowercase = mEnforceLowercase;
381  return NS_OK;
382 }
383 NS_IMETHODIMP sbTextPropertyInfo::SetEnforceLowercase(PRBool aEnforceLowercase)
384 {
386  mEnforceLowercase = aEnforceLowercase;
387  return NS_OK;
388 }
389 
390 NS_IMETHODIMP sbTextPropertyInfo::GetNoCompressWhitespace(PRBool *aNoCompressWhitespace)
391 {
392  NS_ENSURE_ARG_POINTER(aNoCompressWhitespace);
394  *aNoCompressWhitespace = mNoCompressWhitespace;
395  return NS_OK;
396 }
397 NS_IMETHODIMP sbTextPropertyInfo::SetNoCompressWhitespace(PRBool aNoCompressWhitespace)
398 {
400  mNoCompressWhitespace = aNoCompressWhitespace;
401  return NS_OK;
402 }
NS_IMETHOD Sanitize(const nsAString &aValue, nsAString &_retval)
return NS_OK
const unsigned long TRANSFORM_IGNORE_NONALPHANUM_IGNORE_SPACE
const unsigned long TRANSFORM_IGNORE_LEADING
TRANSFORM_IGNORE_* operates on leading characters and stops as soon as a non-ignored character is fou...
onPageChanged aValue
Definition: FeedWriter.js:1395
void SB_CompressWhitespace(nsAString &aString, PRBool aLeading, PRBool aTrailing)
NS_IMPL_ADDREF_INHERITED(sbTextPropertyInfo, sbPropertyInfo)
NS_IMETHOD MakeSortable(const nsAString &aValue, nsAString &_retval)
NS_IMETHOD Validate(const nsAString &aValue, PRBool *_retval)
this _dialogInput val(dateText)
PRLock * mNoCompressWhitespaceLock
The property information specific to text fields.
An interface used to describe a metadata property for use by the UI and other sbILibrary interfaces (...
const unsigned long TRANSFORM_IGNORE_KEEPNUMBERSYMBOLS
TRANSFORM_IGNORE_* keeps number symbols in.
nsCOMArray< sbIPropertyOperator > mOperators
const unsigned long TRANSFORM_IGNORE_NONSPACE
Ignore non-spacing characters. This includes but is not limited to diacritics.
NS_IMETHOD MakeSearchable(const nsAString &aValue, nsAString &_retval)
NS_IMPL_RELEASE_INHERITED(sbTextPropertyInfo, sbPropertyInfo)
NS_IMETHOD Format(const nsAString &aValue, nsAString &_retval)
#define SB_STRINGTRANSFORM_CONTRACTID