Spring Modules Validation
Spring Modules Validation
Spring b E ample
Prev
Ne t
2009 T V T S M S , V . . T
V . P
0.9
1. Valang
V
VlnVld o aagaia , ' og pig aeok aiainVld o. . nf m . ld o.aia
Va-lidation La g-uage. I S V
. O
B V B B
SUET TDN
. 0.91 (B P D F .I V ) .T . .
F .
.T
p oTp EUL [og pigo l .aiaineapeP oTp.TDN' e n e QAS ' . nmd e ld o. ml.e n eSUET]
p oTp EUL [og pigo l .aiaineapeP o$e oTp.TDN' e n e QAS ' . nmd e ld o. ml.e nP n eSUET]
.I
p oTp e n e
, 'STUDENT'. O
pie<10 c 0
I S F
A F
. W
). S
'IN'/'NOT IN' S S ,
.S
S .
1/11
12/14/11
ValangValidateTag needing it, but running Valang no longer requires it. This involved removing ServletContextAware from it's custom dependency injection. If someone was using this in a custom function, the function can now be configured directly in Spring and Spring can inject any "aware" values. Changed logging to use SLF4J api. Version 0.92 Removed custom dependency injection since functions can be configured in Spring. Added auto-discovery of FunctionWrapper beans from the Spring context to go with existing auto-discovery of FunctionDefinition beans. Version 0.93 Made specific comparison classes for each operator for a performance improvement. Changed IS WORD and IS BLANK to use Commons Lang StringUtils, which will change the behavior slightly but should be more accurate to the description of the validation. Change Operator from interfaces to an enum and removed OperatorConstants. Fixed bytecode generation to handle a M p a L , and an Array. a, i Version 0.94 Upgraded to Spring 3.0 and changed group & artifact IDs to match standard Spring naming conventions. Note Support for the where clause has not been added to the JavaScript custom tag currently.
Rule S nta
The basic construction of a Valang rule is to have it begin and end with a brace. Within the braces, the default property name for the rule is specified first. Then the Valang expression, followed by the default error message. These are all the required values for a Valang rule. The other optional values for a rule are the error message key and arguments for it. Each of the values of the rule are delimitted by a colon. { <property-name> : <expression> : <default-error-message> : <error-message-ke > : <error-message-args>
Table 1. Rule S nta Rule Value Description Required This is the default property of the bean being targeted for propertye validation, and can be referred to with the shortcut ? in an name expression. e expression The Valang expression. defaultThe default error message. If this isn't needed, it can be left blank e erroreven though it's required. message errorfle a message- The message resource key for the i18n error message. key errorIf the error-message-ke is specified, arguments for the error a message- message can also be set as the final value of the rule. This accepts f l e arg a comma delimited list of values.
E pression S nta
The expression language provides an English like syntax for expressing validation rules. There are a number of operators for comparing a value to another. Logical expressions, resulting in e or f l e can be grouped together with parentheses to form more complex expressions. a , Just to give some context to the explanation of all the rules, below is a simple example. The bean being validated has the properties e i springb e ample.org/e amples/spring-modules-validation-module.html g F
Nm(, g L Nm(, ae) e a ae)
2/11
12/14/11
bean being validated has the properties g F e i N m ( , g L N m ( , and g A e ) The first two ae) e a ae) e g(. return a S i g and the last returns an i . The default property is 'firstName', which is referred n n to by the question mark. The first part of the rule enclosed in parentheses checks if the first name is either 'Joe' or it's length is greater than 5. The next part checks if the last name is one of the values in the list, and the final part checks if the age is over 18.
( EUL 'o'O ln h? >5 ADl Nm I 'ono' 'oe' 'm h ADae>1 ? QAS Je R eg () ) N a ae N Jh n, Jn , Si ' N g 8
Operator S nta The parser is not case sensitive when processing the operators. Table 2. E pression Operators Comparison Operator = == IS EQUALS Description Supports Strings, booleans, numbers, dates, and enums. Strings, booleans, numbers, dates, and enums. Numbers and dates. Numbers and dates. Numbers and dates. E ample
!= <> >< IS Checks for inequality. NOT NOT EQUALS > GREATER THAN IS GREATER THAN < LESS THAN IS LESS THAN >= => GREATER THAN OR EQUALS IS GREATER THAN OR EQUALS <= =< LESS THAN OR EQUALS IS LESS THAN OR EQUALS NULL IS NULL IS NOT NOT NULL NULL HAS TEXT HAS NO TEXT HAS LENGTH HAS NO LENGTH IS BLANK IS NOT BLANK Checks if a value is greater than another. Checks if a value is less than another. Checks if a value is greater than or equal to another.
ae>1 g 8 ae>1 g 8
ae> 1 g = 8
Checks if a value is less than or equal to another. Checks if a value is n l . l Checks if a value is not n l . l Checks if the value has at least one non-whitespace character. Checks if the value doesn't have a non-whitespace character. Checks if the value's length is greater than zero. Checks if the value's length is zero. Checks if the value is blank (n l or l zero length). Checks if the value isn't blank (not n l , length greater than zero). l
Numbers and dates. Objects. Objects. Strings. Strings. Strings. Strings. Strings. Strings. Strings.
ae< 1 g = 8 f i Nm I ae S NL UL f i Nm I ae S NTNL O UL f i Nm HS ae A TX ET f i Nm HS ae A N TX O ET f i Nm HS ae A LNT EGH f i Nm HS ae A N LNT O EGH f i Nm I ae S BAK LN f i Nm I ae S NTBAK O LN f i Nm I ae S UPRAE PECS
IS UPPERCASE IS UPPER CASE IS Checks if the value is uppercase. UPPER IS NOT UPPERCASE IS NOT UPPER Checks if the value isn't uppercase. CASE IS NOT UPPER IS LOWERCASE IS LOWER CASE Checks if the value is lowercase. IS LOWER IS NOT LOWERCASE IS NOT LOWER CASE Checks if the value isn't lowercase. springb e ample.org/e amples/spring-modules-validation-module.html
Strings.
f i Nm I ae S NTUPRAE O PECS
Strings.
f i Nm I ae S LWRAE OECS
f i
Nm I ae S
Strings.
NTLWRAE O OECS
3/11
12/14/11
NOT LOWER CASE IS NOT LOWER IS WORD IS NOT WORD BETWEEN NOT BETWEEN
Checks if the value isn't lowercase. Checks if the value has one or more letters or numbers (no spaces or special characters). Checks if the value doesn't have one or more letters or numbers (no spaces or special characters). Checks if a value is between two other values. Checks if a value isn't between two other values. Checks if a value is in a list.
Strings. Strings. Strings. Numbers and dates. Numbers and dates. Strings, booleans, numbers, dates, and enums. Strings, booleans, numbers, dates, and enums. Any expression. Booleans Any expression. Any expression. Any expression. Any expression.
NTLWRAE O OECS f i Nm I ae S WR OD f i Nm I ae S NTWR O OD aeBTEN1 g EWE 8 AD6 N 5 aeNTBTEN g O EWE 1 AD6 8 N 5 f i Nm I ae N 'o' 'ak, Je, Jc' 'ae,'il Jn' Jl'
IN
NOT IN
Checks if a value isn't in a list. Checks for the opposite of the following expression. Changes a boolean expression to it's opposite. Used to join together the logical comparisons on either side of the operator. Both must evaluate to e . Used to join together the logical comparisons on either side of the operator. Only one must evaluate to e . If the where expression is true, then the main expression for validation is performed. Otherwise it isn't evaluated and no errors are generated. A reference to the bean passed in for validation, which could be passed into a custom function for example.
f i Nm NT ae O I 'o' N Je, 'ak,'ae, Jc' Jn' 'il Jl' NTf O i Nm ae EUL 'o' QAS Je m ce(\ +, a h '\ ' f i Nm)I ! ae S (RE TU) f i Nm ae EUL 'o' QAS Je ADae>2 N g 1 f i Nm ae EUL 'o'O QAS Je R ae>2 g 1 f i Nm ae EUL 'o' QAS Je WEEae>2 HR g 1 iVld h ) ai( i I TU S RE
NOT ! AND
OR
WHERE
this
Literal S nta
E ample
'Joe' are surrounded by single quotes. Numbers can be expressed without any Numbers special syntax. 1, 100, 0.73, -2.48 Numbers are all parsed using Bgeia. iDcml Date literals are surrounded by brackets. These are the supported formats supported by the Df lD ea e. ea a P
Dates
4/11
12/14/11
MMdd, MM-dd, -MMdd HH:mm:ss, MMdd HHmmss, MMdd HH:mm:ss, MM-dd HHmmss There are four different constants for boolean values. The values Booleans 'TRUE' and 'YES' TRUE, YES, FALSE, NO represent t u , re and the values 'FALSE' and 'NO' represent f l e as Enums are surrounded by bracket and single quotes. If the full path to the enum isn't specified, it will be resolved ['FAIL'], ['org.springmodules.validation.valang.CreditStatus.FAIL'], Enums when the ['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT'] expression is evaluated by looking up the enum value from enum on the opposite side of the expression.
Mathematical Operator S nta Valang supports basic mathematical formulas based on numeric literals and property values. Table 4. Mathematical E pression Operators Mathematical Operator + * / DIV % MOD Description Addition operator. Subtraction operator. Multiplication operator. Division operator. Modulo operator. E ample
pie+1 rc 2 pie-1 rc 2 pie*12 rc . pie/2 rc ae%1 g 0
Propert S nta Valang supports standard property and nested property access to the bean passed in for validation. Table 5. Propert S nta Propert T pe Description E ample
adesI NT drs S O NL UL adesct I drs.i S NTBAK O LN
Using standard JavaBean property notation, a value from the drs Standard bean being validated may be retrieved. The a d e s represents g t d r s ( on the bean. eAdes) Using standard JavaBean property notation, a nested value from the bean being validated may be retrieved. The Nested a d e s c t represents g t d r s ( . e C t ( on the bean. drs.i eAdes)gti ) From an array, L s , or S t it e springb e ample.org/e amples/spring-modules-validation-module.html , a value from it can be returned by
5/11
12/14/11
List Map
From an array, L , or S , a value from it can be returned by i e specifying it's index. Only arrays and lists are supported by bytecode generation. From a M p the value based on the key specified is retrieved. a,
F nc ion
These are built in functions that come with Valang. The function framework is pluggable, so it's easy to add custom functions. Adding custom functions will be covered in the next section. Table 6. Functions Function Description length Returns the size of a collection or an array, len size and otherwise returns the length of string by count called o i g ) on the object. S n( Performs a match on a regular expression. The match first argument is the regular expression and matches the second is the value match on. email Checks if the value is a valid e-mail address. upper Converts the value to uppercase. lower Converts the value to lowercase. Wraps a string in resolve Df lM aeo cR o al. ea e gS ee l be Checks if the user authenticated by Spring inRole Security is in a role. E ample
ln hf eg (i Nm)<2 ae 0
Nm)I ae S
om F nc ion
Custom functions can either be explicitly registered or instances of F n i n e i i i n and c oDfn o Fn in ap c o W p e are automatically registered with a V l n V l d o . If just specifying a class aagaia name, it must have a constructor with the signature F n i n ] a g m n , i l n , i c l m . c o[ e n ie n o n The F n i n a p c o W p e is specifically for Spring configured functions. If the F n i n in a c o Fn in ap c o W p e takes any arguments, it must implement C n i a l F n i n which allows the ofg be c o parser to configure the arguments, line number, and column number. Otherwise the line & column number will not be set on a Spring configured function. Note It's important for a F n i n a p around a custom F n i n to be of the c oW pe c o scope prototype as well as the F n i n a p . Also the F n i n a p must c oW pe c oW pe have <aop:scoped-pro /> defined so each call to it will get a new instance of the function. This is because as the validation language is parsed a new instance of a function is made each time and has the arguments specific to that function set on it.
Sp ing Config
a ion
The example below shows how to explicitly register a custom function directly with a validator. The custom functions 'validLastName' and 'creditApproval' are registered on the c o F n i n m c o property as a M p The key is the name of the function to be used in the validation language and a. the value if the function being registered, which can either be the fully qualified name of the class or an instance of F n i n a p . c oW pe ValangValidatorCustomFunctionTest-conte t. ml
< m e in"."ecdn=UF8? ? l o=10 noig"T-"> <en mn=h p/ ba l " :/ .pig aeokog ceaba " nf m . / hm/en mn: i" p/ l =h :/ .3og20/MShm-n ac" . /01XLceai ne mn:o=h p/ l ap" :/ .pig aeokog ceaap nf m . / hm/o" i ceaoain" p/ : hmLc o=h :/ .pig aeokog ceaba nf m . / hm/en h p/ :/ .pig aeokog ceaba /pigba . d nf m . / hm/en n-en
h p/ :/
6/11
12/14/11
Instances
of F n t o D f n t o and F n t o W a p r are automaticall ucineiiin ucinrpe registered with a V l n V l d t r The custom functions 'validLastName' and 'creditApproval' are registered. If a aagaiao F n t o W a p r doesn't have a function name specified, the name of the bean will be used for ucinrpe the function name.
ValangValidatorCustomFunctionDiscover Test-conte t. ml
<xlvrin"."ecdn=UF8? ?m eso=10 noig"T-"> <en xls"tp/wwsrnfaeokogshm/en" bas mn=ht:/w.pigrmwr.r/ceabas xlsxi"tp/www.r/01XLceaisac" mn:s=ht:/w.3og20/MShm-ntne xlsap"tp/wwsrnfaeokogshm/o" mn:o=ht:/w.pigrmwr.r/ceaap xlsp"tp/wwsrnfaeokogshm/" mn:=ht:/w.pigrmwr.r/ceap xishmLcto=ht:/w.pigrmwr.r/ceabas s:ceaoain"tp/wwsrnfaeokogshm/en ht:/w.pigrmwr.r/ceabassrn-en.s tp/wwsrnfaeokogshm/en/pigbasxd ht:/w.pigrmwr.r/ceaap tp/wwsrnfaeokogshm/o ht:/w.pigrmwr.r/ceaapsrn-o.s" tp/wwsrnfaeokogshm/o/pigapxd> <encas"r.pigoue.aiainvln.ucin.ucineiiin ba ls=ogsrnmdlsvldto.aagfntosFntoDfnto" pnm=vldatae :ae"aiLsNm" pcasae"r.pigoue.aiainvln.aiLsNmFnto"> :lsNm=ogsrnmdlsvldto.aagVldataeucin/ <- Ue ba nm frfnto nm i ntepiil sto tewapr-> !- ss en ae o ucin ae f o xlcty e n h rpe <eni=ceiApoa" ba d"rdtprvl cas"r.pigoue.aiainvln.ucin.ucinrpe" ls=ogsrnmdlsvldto.aagfntosFntoWapr soe"rttp" cp=pooye> <o:cpdpoy> apsoe-rx/ <rprynm=fnto" poet ae"ucin> <eni=ceiApoaFnto" ba d"rdtprvlucin cas"r.pigoue.aiainvln.rdtprvlucin ls=ogsrnmdlsvldto.aagCeiApoaFnto" soe"rttp" cp=pooye> <rprynm=ceiRtnLs" poet ae"rdtaigit> <it ls> <au>OD/au> vleGO<vle <au>XELN<vle vleECLET/au> <ls> /it <poet> /rpry <ba> /en <poet> /rpry <ba> /en <eni=proVldtr cas"r.pigoue.aiainvln.aagaiao" ba d"esnaiao" ls=ogsrnmdlsvldto.aagVlnVldtr> <rprynm=casae vle"r.pigoue.aiainvln.esn/ poet ae"lsNm" au=ogsrnmdlsvldto.aagPro"> <!Fnlvldto tssta teapsoe-rx i wrigsnei tesm isac ia aiain et ht h o:cpdpoy s okn ic f h ae ntne o CeiApoaFnto i ue i wl b stt afiigvlefrbt sdso teo. f rdtprvlucin s sd t il e e o aln au o oh ie f h r Wiei toisacsaemd tefrtcniinsol ps wietescn wl fi. hl f w ntne r ae h is odto hud as hl h eod il al -> <rprynm=vln" poet ae"aag> <au>!CAA vle<[DT[
7/11
12/14/11
Code E ample Checks if the last name is in a list, and if it isn't f l e is returned. as E ample 1. V l d a N m F n i n aiL ae c o
pbi casVldataeucinetnsAsrcFnto { ulc ls aiLsNmFnto xed btatucin fnlLge lge =LgeFcoygtogrVldataeucincas; ia ogr ogr ogratr.eLge(aiLsNmFnto.ls) fnlStSrn>laiLsNms=nwHsStSrn>) ia e<tig Vldatae e ahe<tig(; /* * *Cntutr osrco * / pbi VldataeucinFnto[ agmns itln,itclm){ ulc aiLsNmFnto(ucin] ruet, n ie n oun spragmns ln,clm) ue(ruet, ie oun; dfndxcNmeOAgmns1; eieEatubrfruet() laiLsNmsad"nesn) Vldatae.d(Adro"; laiLsNmsad"ako"; Vldatae.d(Jcsn) laiLsNmsad"ono"; Vldatae.d(Jhsn) laiLsNmsad"oe"; Vldatae.d(Jns) laiLsNmsad"mt"; Vldatae.d(Sih) /* * *Cek i tels nm i bokd hcs f h at ae s lce. * *@eun rtr Ojc bet Rtrsa<oeboen/oe fr eun cd>ola<cd> o * wehro nttels nm i bokd hte r o h at ae s lce. * / @vrie Oerd poetdOjc dGteutOjc tre){ rtce bet oeRsl(bet agt boenrsl =tu; ola eut re Srn smo =gtruet([]gteuttre)tSrn(; tig ybl eAgmns)0.eRsl(agt.otig) i (laiLsNmscnan(ybl){ f !Vldatae.otissmo) rsl =fle eut as; rtr rsl; eun eut
The function checks if a person can get credit approval. Their credit rating is checked against a list onl if the are over 18 ears old. E ample 2. C n i a l F n i n ofg be c o
pbi casCeiApoaFnto etnsAsrcFnto ulc ls rdtprvlucin xed btatucin ipeet CniualFnto { mlmns ofgrbeucin fnlLge lge =LgeFcoygtogrCeiApoaFnto.ls) ia ogr ogr ogratr.eLge(rdtprvlucincas; StPro.rdtaig lrdtaig =nwHsStPro.rdtaig(; e<esnCeiRtn> CeiRtns e ahe<esnCeiRtn>) /* * *Cntutr osrco * / pbi CeiApoaFnto( { ulc rdtprvlucin) /* * *Cntutr osrco * / pbi CeiApoaFnto(ucin]agmns itln,itclm){ ulc rdtprvlucinFnto[ ruet, n ie n oun spragmns ln,clm) ue(ruet, ie oun; dfndxcNmeOAgmns2; eieEatubrfruet() lrdtaig.d(esnCeiRtn.AR; CeiRtnsadPro.rdtaigFI) lrdtaig.d(esnCeiRtn.OD; CeiRtnsadPro.rdtaigGO) lrdtaig.d(esnCeiRtn.XELN) CeiRtnsadPro.rdtaigECLET;
8/11
12/14/11
B tecode Generation
I , . I ' ' . , . T ,
Fnto ucin
'
'
No e O P
Mp a,
Ls, it
'
.A
St e.
, , P F $$V '
. A . T .
'B
Dfutiio -Gnrtdbtcd frogsrnmdlsvldto.aagPro.eLsNm( ealVstr eeae yeoe o r.pigoue.aiainvln.esngtatae) a 'r.pigoue.aiainvln.esnataeenrpryucin$aag. s ogsrnmdlsvldto.aagProLsNmBaPoetFnto$Vln' Dfutiio -Gnrtdbtcd frogsrnmdlsvldto.aagPro.eAe) ealVstr eeae yeoe o r.pigoue.aiainvln.esngtg( a 'r.pigoue.aiainvln.esngBaPoetFnto$Vln' s ogsrnmdlsvldto.aagProAeenrpryucin$aag. Dfutiio -Gnrtdbtcd frogsrnmdlsvldto.aagPro.eCeiRtn( ealVstr eeae yeoe o r.pigoue.aiainvln.esngtrdtaig) a 'r.pigoue.aiainvln.esnrdtaigenrpryucin$aag. s ogsrnmdlsvldto.aagProCeiRtnBaPoetFnto$Vln' Dfutiio -Gnrtdbtcd frogsrnmdlsvldto.aagPro.eFrtae) ealVstr eeae yeoe o r.pigoue.aiainvln.esngtisNm( a 'r.pigoue.aiainvln.esnisNmBaPoetFnto$Vln' s ogsrnmdlsvldto.aagProFrtaeenrpryucin$aag. Dfutiio -Gnrtdbtcd frogsrnmdlsvldto.aagPro.eCeiSau( ealVstr eeae yeoe o r.pigoue.aiainvln.esngtrdttts)
a 'r.pigoue.aiainvln.esnrdtttsenrpryucin$aag. s ogsrnmdlsvldto.aagProCeiSauBaPoetFnto$Vln'
9/11
12/14/11
a 'r.pigoue.aiainvln.esnrdtttsenrpryucin$aag. s ogsrnmdlsvldto.aagProCeiSauBaPoetFnto$Vln' VlnVldtrefracTs -To 79.n. aagaiaoPromneet ok 080s VlnVldtrefracTs -To 22.n. aagaiaoPromneet ok 140s VlnVldtrefracTs -Msaevldtrto 79.n,adbtcd msaevlitrto 22.n. aagaiaoPromneet esg aiao ok 080s n yeoe esg adao ok 140s
Results from V l n V l d t r e f r a c T s which was run on a Macbook Pro (2.5GHz Intel Dual aagaiaoPromneet Core 2 Duo with 4 GB RAM with OS X 10.5.6) with Java 5. All the expressions are identical, but adjusted to either retrieve the values being compared from a JavaBean, M p L s , or an array. a, it Table 7. B tecode Generation Performance Comparison E pression Reflection B tcode Generation
{ lastName : validLastName(?) is true AND creditApproval(age, creditRating) is true WHERE firstName IN 'Joe', 'Jack', 'Jill', 'Jane' AND creditStatus IN ['org.springmodules.validation.valang.CreditStatus.PENDING'], 7098ns ['org.springmodules.validation.valang.CreditStatus.FAIL'] AND creditRating EQUALS ['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT'] AND age > 18 : '' { mapVars[lastName] : validLastName(?) is true AND creditApproval(mapVars[age], mapVars[creditRating]) is true WHERE mapVars[firstName] IN 'Joe', 'Jack', 'Jill', 'Jane' AND mapVars[creditStatus] IN ['org.springmodules.validation.valang.CreditStatus.PENDING'], 4902ns ['org.springmodules.validation.valang.CreditStatus.FAIL'] AND mapVars[creditRating] EQUALS ['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT'] AND mapVars[age] > 18 : '' { listVars[1] : validLastName(?) is true AND creditApproval(listVars[2], listVars[4]) is true WHERE listVars[0] IN 'Joe', 'Jack', 'Jill', 'Jane' AND listVars[3] IN ['org.springmodules.validation.valang.CreditStatus.PENDING'], 2704ns ['org.springmodules.validation.valang.CreditStatus.FAIL'] AND listVars[4] EQUALS ['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT'] AND listVars[2] > 18 : '' { vars[1] : validLastName(?) is true AND creditApproval(vars[2], vars[4]) is true WHERE vars[0] IN 'Joe', 'Jack', 'Jill', 'Jane' AND vars[3] IN ['org.springmodules.validation.valang.CreditStatus.PENDING'], ['org.springmodules.validation.valang.CreditStatus.FAIL'] AND vars[4] 2918ns EQUALS ['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT'] AND vars[2] > 18 : ''
2124ns
237ns
226ns
212ns
Spring Config ra ion By specifying the 'className' property, bytecode will be generated for each method being called to avoid reflection. This gives a significant performance improvement.
10/11
12/14/11
Date E amples
The default date parser provides support for a number of different date literals, and also has support for shifting and manipulating dates. Below are a few examples, but see the D f u t a e a s r for more detailed information. ealDtPre Spring Configuration ValangValidatorDateTest-conte t. ml
<xlvrin"."ecdn=UF8? ?m eso=10 noig"T-"> <en xls"tp/wwsrnfaeokogshm/en" bas mn=ht:/w.pigrmwr.r/ceabas xlsxi"tp/www.r/01XLceaisac" mn:s=ht:/w.3og20/MShm-ntne xlsap"tp/wwsrnfaeokogshm/o" mn:o=ht:/w.pigrmwr.r/ceaap xishmLcto=ht:/w.pigrmwr.r/ceabas s:ceaoain"tp/wwsrnfaeokogshm/en ht:/w.pigrmwr.r/ceabassrn-en.s tp/wwsrnfaeokogshm/en/pigbasxd ht:/w.pigrmwr.r/ceaap tp/wwsrnfaeokogshm/o ht:/w.pigrmwr.r/ceaapsrn-o.s" tp/wwsrnfaeokogshm/o/pigapxd> <eni=proVldtr cas"r.pigoue.aiainvln.aagaiao" ba d"esnaiao" ls=ogsrnmdlsvldto.aagVlnVldtr> <rprynm=casae vle"r.pigoue.aiainvln.esn/ poet ae"lsNm" au=ogsrnmdlsvldto.aagPro"> <rprynm=vln" poet ae"aag> <!Tidt ls vldto sit '081-0y t '080-10:00' hr o at aiain hfs 20-23<' o 20-10 00:0 Scn t ls vldto sit '050-92:00<+0+H t '050-10:00' eod o at aiain hfs 20-40 33:0M1d8' o 20-41 80:0. Ls sit '090-60:00<+0't '090-10:00' at hfs 20-20 00:0M2y o 22-20 00:0. -> <au>!CAA vle<[DT[ {lsUdtd:?>[0820 :' atpae 2013] ' {lsUdtd:?>[081-0 :' atpae 20-23] ' {lsUdtd:?>[081-01:03]:' atpae 20-23 22:1 ' {lsUdtd:?>[0820123]:' atpae 2013 201 ' {lsUdtd:?>[08201:03]:' atpae 2013 22:1 ' {lsUdtd:?>[081-0123]:' atpae 20-23 201 ' {lsUdtd:?BTEN[0820 AD[090-60:00<+0]:' atpae EWE 2013] N 20-20 00:0M2y ' {lsUdtd:?>[081-0y :' atpae 20-23<] ' {lsUdtd:?>[050-92:00<+0+H :' atpae 20-40 33:0M1d8] ' {lsUdtd:?<[090-60:00<+0]:' atpae 20-20 00:0M2y ' ]</au> ]<vle <poet> /rpry <ba> /en <bas /en>
Pre 5. Reference
Up Home
Ne t 2. Do nload
11/11