-- DLS v3.3.14	
-- Params in HTTP request:
-- @PNR, a list of Person.Personnummer.personnummer 

-- @HAENPRIVATEFRADATO, a date, always cast to date as in yyyy.MM.dd 
-- @HAENPRIVATETILDATO, a date, always cast to date as in yyyy.MM.dd
-- @HAEN, a list of 

-- @HAENKODEPRIVATEFRADATO, a date, always cast to date as in yyyy.MM.dd 
-- @HAENKODEPRIVATETILDATO, a date, always cast to date as in yyyy.MM.dd
-- @HAENKODE, a list of 

-- @FOEDSELSDATO, a date, always cast to date as in yyyy.MM.dd

	--names
-- @FORNAVNE
-- @MELLEMNAVNE
-- @EFTERNAVN
-- @ADRESSERINGSNAVN
-- @NAVNEEKSAKT, which can be null (=false), true, eller false. 

	--address fields
-- @DARADRESSE
-- @KOMKOD
-- @POSTNR
-- @POSTDISTRIKT
-- @VEJKODE
-- @VEJADRESSERINGSNAVN
-- @VEJNAVN
-- @HUSNR if query strings contains  ?husnr=&xx=abc, @HUSNR should be set to '', an empty string
-- @BYGNININGSNR
-- @SIDEDOER
-- @ETAGE

/*
In order to make the pseudu-sql easier to read, the clauses has been shorten.
E.g 
CprAdresse.postnummer = @POSTNR 
should be replaced with
(Person.id IN (SELECT personid FROM Cpradresse WHERE Cpradresse.postnummer = @POSTNR ) )

Navn.navnesoegning LIKE sanitizeForLikeSearchField(@FORNAVNE, @MELLEMNAVNE, @EFTERNAVN, @ADRESSERINGSNAVN)

Should be replaced with
(Person.id (SELECT personid FROM Navn WHERE Navn.navnesoegning LIKE sanitizeForLikeSearchField(@FORNAVNE, @MELLEMNAVNE, @EFTERNAVN, @ADRESSERINGSNAVN)) )


All compares must be case in-sensitive.
The solution shall enable the retrieval of the totalCount for the searched content.
*/


/* Generally Adressebeskyttelsescheck (Addressprotectioncontrol), shall be used where this comment is added = /*ADRESSEBESKYTTELSECHECK*/  */
AS TABEL INNER JOIN TABEL.personid not in (SELECT BESKYTTELSE.personid FROM BESKYTTELSE WHERE BESKYTTELSE.personid = TABEL.personid
					   AND BESKYTTELSE.beskyttelsestype='navne_og_adresse' 
					   AND BESKYTTELSE.status = 'aktuel' )
					   
/* 
   The Adressebeskyttelsescheck is a little bit different for Adresse and UDREJSEINDREJSE where there are visible (SYNLIG) fields despite outcome of ADRESSEBESKYTTELSECHECK.
   ADRESSEBESKYTTELSECHECK_UDINDREJSE:
   virkningfra and virkningFraUsikkerhedsmarkering are always visible
*/
SELECT distinct UDINDREJSE_SYNLIG.personid, UDINDREJSE_SYNLIG.virkningfra, UDINDREJSE_SYNLIG.virkningFraUsikkerhedsmarkering, UDINDREJSE_MED_BESKYTTELSE.* FROM UDREJSEINDREJSE UDINDREJSE_SYNLIG
    LEFT JOIN (SELECT * FROM UDREJSEINDREJSE WHERE PERSON.id = personid /*ADRESSEBESKYTTELSECHECK*/ ) UDINDREJSE_MED_BESKYTTELSE
        ON UDINDREJSE_SYNLIG.personid = UDINDREJSE_MED_BESKYTTELSE.personid AND UDINDREJSE_SYNLIG.virkningfra = UDINDREJSE_MED_BESKYTTELSE.virkningfra
/* 
   ADRESSEBESKYTTELSECHECK_Adresse:
   virkningfra and virkningFraUsikkerhedsmarkering are always visible 
*/
SELECT distinct Adresse_SYNLIG.personid, Adresse_SYNLIG.virkningfra, Adresse_SYNLIG.virkningFraUsikkerhedsmarkering, Adresse_MED_BESKYTTELSE.* FROM Adresse Adresse_SYNLIG
    LEFT JOIN (SELECT * FROM Adresse WHERE PERSON.id = personid /*ADRESSEBESKYTTELSECHECK*/ ) Adresse_MED_BESKYTTELSE
        ON UDINDREJSE_SYNLIG.personid = Adresse_MED_BESKYTTELSE.personid AND UDINDREJSE_SYNLIG.virkningfra = Adresse_MED_BESKYTTELSE.virkningfra


-- /* REQUIRED OUTPUT */ indicates (by @requiredField) which attributes or objects are required in the Json output. REQUIRED OUTPUT is influenced by ADRESSEBESKYTTELSECHECK.

/* PseudoSQL til CprPrivate all methods in one */
SELECT 
	statusdato, 	-- /* REQUIRED OUTPUT */
	statusdatoUsikkerhedsmarkering, -- /* REQUIRED OUTPUT */
	BESKYTTELSE.*, 	-- /* REQUIRED OUTPUT */
	PERSONNUMMER.*,	-- Protection (BESKYTTELSE) of name and address in JOIN
	NAVN.*,			-- /* REQUIRED OUTPUT */ -- Protection (BESKYTTELSE) of name and address in JOIN 
	VAERGEMAAL.*,	-- /* REQUIRED OUTPUT */
	FORSVINDING.*,	-- /* REQUIRED OUTPUT */
	Adresse.*, 		-- /* REQUIRED OUTPUT */ -- Protection (BESKYTTELSE) of name and address in JOIN. Check conditions on visible fields, which are outsite the protection, under ADRESSEBESKYTTELSECHECK_Adresse 
	UDREJSEINDREJSE.*,	-- /* REQUIRED OUTPUT */ -- Protection (BESKYTTELSE) of name and address in JOIN. Check conditions on visible fields, which are outsite the protection, under ADRESSEBESKYTTELSECHECK_UDINDREJSE 
	KONTAKTADRESSE.*,	-- /* REQUIRED OUTPUT */ -- May be shown even though the person has protection (BESKYTTELSE) of name and address, this applies only for persons which have status in ('udrejst','forsvundet','doed')
	ADMINISTRATIVENHED.*, -- /* REQUIRED OUTPUT */
	CPRHAENDELSESKODE.*
FROM PERSON 
  LEFT JOIN BESKYTTELSE 	ON PERSON.id = BESKYTTELSE.personid AND BESKYTTELSE.beskyttelsestype <> "lokal_vejviser" AND  BESKYTTELSE.status = 'aktuel'
  LEFT JOIN PERSONNUMMER 	ON (@PNR IS NOT NULL AND -- Only if personnummer parameter (@PNR) is pressent. May the personnummer be returned 
								PERSON.id = PERSONNUMMER.personid AND (PERSONNUMMER.status = 'aktuel' 
								OR (PERSONNUMMER.status = 'historisk' AND PERSONNUMMER.personnummer in (@PNR))) -- PERSONNUMMER.status = 'historisk' can only be shown for those Person objects that reflect search with PERSONNUMMER.status <> 'aktuel'  
  LEFT JOIN NAVN 			ON PERSON.id = NAVN.personid 
								/* ADRESSEBESKYTTELSECHECK */
								and NAVN.status = 'aktuel'
  LEFT JOIN FORSVINDING 	ON PERSON.id = FORSVINDING.personid 
								and FORSVINDING.status = 'aktuel'
  LEFT JOIN VAERGEMAAL 			ON PERSON.id = VAERGEMAAL.personid -- No protection (BESKYTTELSE) of name and address for VAERGEMAAL
									AND VAERGEMAAL.status = 'aktuel'
  LEFT JOIN UDREJSEINDREJSE		ON PERSON.id = UDREJSEINDREJSE.personid
  								/* ADRESSEBESKYTTELSECHECK */
  								INNER JOIN ADMINISTRATIVENHED AS ADMENHEDINDREJSE ON ADMENHEDINDREJSE.kode = UDREJSEINDREJSE.cprlandekodeindrejse
	                            INNER JOIN ADMINISTRATIVENHED AS ADMENHEDUDREJSE ON ADMENHEDUDREJSE.kode = UDREJSEINDREJSE.cprlandekodeudrejse
								and UDREJSEINDREJSE.status = 'aktuel'

/* Kontaktadresse may be shown even though the person has protection (BESKYTTELSE) of name and address, this applies only for persons which have status in ('udrejst','forsvundet','doed') */
  LEFT JOIN KONTAKTADRESSE AS SimpelAdresse	ON PERSON.id = SimpelAdresse.personid 
  								and SimpelAdresse.status = 'aktuel' and PERSON.status in ('doed','forsvundet','udrejst')
/* Cprhaendelse and Cprhaendelseskode may be shown even though the person has protection (BESKYTTELSE) of name and address. Only Cprhaendelse and Cprhaendelseskode for a limited period may be shown. */
  LEFT JOIN CPRHAENDELSE AS Cprhaendelse	ON PERSON.id = Cprhaendelse.personid AND Cprhaendelse.rettetden >= DATE(CURRENT DATE - 7 DAYS)
  LEFT JOIN CPRHAENDELSESKODE AS Cprhaendelseskode	ON PERSON.id = Cprhaendelseskode.personid AND Cprhaendelseskode.registreringFra >= DATE(CURRENT DATE - 7 DAYS)
/*Statusdato og statusdatoUsikkerhedsmarkering may only be shown for specific status instances. The parameters may be shown regardless of protection status (beskyttelse). */
  /*
	For 'forsvundet' the parameter holds the disappearance date. 
	For 'udrejst' the parameter holds the date of leaving. 
	For 'doed' the parameter holds the death date. 
	For 'ej_bopael', 'annulleret', 'nedlagt_person' holds the date of status change.
	For all other status instances the value is null. 
  */
  Case WHEN person.status = 'ej_bopael' OR 
			person.status = 'annulleret' OR 
			person.status = 'nedlagt_person' OR 
			person.status = 'forsvundet' OR 
			person.status = 'udrejst' OR 
			person.status = 'doed' 
  THEN
	SELECT statusdato, statusdatoUsikkerhedsmarkering FROM person where PERSONNUMMER.personnummer in (@PNR) -- reflect the attributes for specific searched Person object within the input personnummer list
  ELSE
	SELECT NULL AS 'statusdato', NULL AS 'statusdatoUsikkerhedsmarkering' FROM person where PERSONNUMMER.personnummer in (@PNR)
  END
  
  /*Either danish addresse or 'udrejst'*/ 
  	Case When person.status = 'doed'  /* Person is dead */
  /* FORSVINDING as address (only date) shall be included in CASE (empty "record") */ 
  /* DOED after FORSVINDING (person.status = 'doed' && FORSVINDING.status = 'aktuel') as address (only date) shall be included in CASE (empty "record") */
	  Begin
		/* Logic for fetching adresse for a person who has been declared dead*/
		/* Deliver always latest historic 'adresse'*/
		LEFT OUTER JOIN 
		   ((select top 1 from 
				(SELECT  personid, conavn, bygningsnummer, bynavn, cprKommunekode, AdEnhedKommune.navn as 'cprKommunenavn', cprVejkode, etage, husnummer, 
					postdistrikt, postnummer, sidedoer, vejadresseringsnavn, vejnavn, darAdresse, 
					NULL AS 'CprLandUdrejse.kode', NULL AS 'CprLandUdrejse.navn', NULL AS 'CprLandUdrejse.landekode', NULL AS 'CprLandUdrejseType.typeKode', NULL AS 'CprLandUdrejseType.typeNavn',
					NULL AS 'udenlandsadresselinie1', NULL AS 'udenlandsadresselinie2', 					
					NULL AS 'udenlandsadresselinie3', NULL AS 'udenlandsadresselinie4', NULL AS 'udenlandsadresselinie5' 
				FROM cpradresse
				INNER JOIN AdministrativEnhed AS AdEnhedKommune ON AdEnhedKommune.kode = cprKommunekode
				WHERE cpradresse.status = 'historisk' 
				order by virkningfra desc
				UNION
				SELECT personid, NULL AS 'conavn', NULL AS 'bygningsnummer', NULL AS 'bynavn', NULL AS 'cprKommunekode', 
						NULL AS 'cprKommunenavn', NULL AS 'cprVejkode', NULL AS 'etage', NULL AS 'husnummer', 
						NULL AS 'postdistrikt', NULL AS 'postnummer', NULL AS 'sidedoer', 
						NULL AS 'vejadresseringsnavn', NULL AS 'vejnavn', NULL AS 'darAdresse', 
						CprLandUdrejse.kode, CprLandUdrejse.navn, CprLandUdrejse.landekode, CprLandUdrejseType.typeKode, CprLandUdrejseType.typeNavn, 
						udenlandsadresselinie1, udenlandsadresselinie2, 
						udenlandsadresselinie3, udenlandsadresselinie4,  udenlandsadresselinie5
				FROM UdrejseIndrejse
				INNER JOIN AdministrativEnhed AS CprLandUdrejse ON CprLandUdrejse.kode = cprLandekodeUdrejse INNER JOIN AdministrativEnhedType AS CprLandUdrejseType ON CprLandUdrejse.typeKode = CprLandUdrejseType.typeKode
				WHERE udrejseIndrejse.status = 'aktuel' order by virkningfra desc)
						as ophold ON ophold.personid = Person.id
			) AS DOED_ADRESSE /* ADRESSEBESKYTTELSECHECK */
			 		
			)
      End
	else /* Person has NOT been declared dead */
	  Begin
		-- Logic for fetching possible current address / Should be all historical addresses!
		LEFT OUTER JOIN 
			(((SELECT personid, conavn, bygningsnummer, bynavn, cprKommunekode, AdEnhedKommune.navn as 'cprKommunenavn', cprVejkode, etage, 
						husnummer, postdistrikt, postnummer, sidedoer, vejadresseringsnavn, vejnavn, darAdresse, 
						NULL AS 'CprLandUdrejse.kode', NULL AS 'CprLandUdrejse.navn', NULL AS 'CprLandUdrejse.landekode', NULL AS 'CprLandUdrejseType.typeKode', NULL AS 'CprLandUdrejseType.typeNavn',
						NULL AS 'udenlandsadresselinie1', NULL AS 'udenlandsadresselinie2', NULL AS 'udenlandsadresselinie3', 
						NULL AS 'udenlandsadresselinie4', NULL AS 'udenlandsadresselinie5' 
				FROM cpradresse
				INNER JOIN AdministrativEnhed AS AdEnhedKommune ON AdEnhedKommune.kode = cprKommunekode
				WHERE cpradresse.status = 'aktuel' 
			UNION
			SELECT personid, NULL AS 'conavn', NULL AS 'bygningsnummer',NULL AS 'bynavn',NULL AS 'cprKommunekode', 
					NULL AS 'cprKommunenavn', NULL AS 'cprVejkode', NULL AS 'etage', NULL AS 'husnummer', 
					NULL AS 'postdistrikt', NULL AS 'postnummer', NULL AS 'sidedoer', NULL AS 'vejadresseringsnavn', NULL AS 'vejnavn', NULL AS 'darAdresse', 
					CprLandUdrejse.kode, CprLandUdrejse.navn, CprLandUdrejse.landekode, CprLandUdrejseType.typeKode, CprLandUdrejseType.typeNavn,  
					udenlandsadresselinie1, udenlandsadresselinie2, udenlandsadresselinie3, 
					udenlandsadresselinie4, udenlandsadresselinie5
			FROM UdrejseIndrejse
			INNER JOIN AdministrativEnhed AS CprLandUdrejse ON CprLandUdrejse.kode = cprLandekodeUdrejse INNER JOIN AdministrativEnhedType AS CprLandUdrejseType ON CprLandUdrejse.typeKode = CprLandUdrejseType.typeKode
			WHERE udrejseIndrejse.status = 'aktuel')
			as ophold ON ophold.personid = Person.id
			) AS AKTUEL_ADRESSE /*ADRESSEBESKYTTELSECHECK*/ 
			)
		
	  End 
	/*End Case*/ AS Adresse

 WHERE 

-- all comparators must be none casesensitive
-- all dates must be cast to a date (not datetime)

  /* Parameters Not final */
    -- validate input parameters 	
		(	
			(
					(@HAENPRIVATEFRADATO IS NULL OR DATEDIFF(day, @HAENPRIVATEFRADATO, NOW()) <= 7 ) -- do not allow event dates older than a week
				AND
					(@HAENPRIVATETILDATO IS NULL AND @HAENPRIVATEFRADATO IS NULL OR DATEDIFF(day, @HAENPRIVATEFRADATO, @HAENPRIVATETILDATO) >= 0 ) -- @HAENPRIVATETILDATO must only be used together with @HAENPRIVATEFRADATO and most be after or same day as @HAENPRIVATEFRADATO. DATEFIFF is expected to return a negative value if date a is after date b.
				AND
					(@HAEN IS NULL OR @HAENPRIVATEFRADATO IS NOT NULL ) -- if @HAEN has a value, @HAENPRIVATEFRADATO must not be null.
			) 
		AND
			(
					(@HAENKODEPRIVATEFRADATO IS NULL OR DATEDIFF(day, @HAENKODEPRIVATEFRADATO, NOW()) <= 7 ) -- do not allow event dates older than a week
				AND
					(@HAENKODEPRIVATETILDATO IS NULL AND @HAENKODEPRIVATEFRADATO IS NULL OR DATEDIFF(day, @HAENKODEPRIVATEFRADATO, @HAENKODEPRIVATETILDATO) >= 0 ) -- @HAENKODEPRIVATETILDATO must only be used together with @HAENKODEPRIVATEFRADATO and most be after or same day as @HAENKODEPRIVATEFRADATO. DATEFIFF is expected to return a negative value if date a is after date b.
				AND
					(@HAENKODE IS NULL OR @HAENKODEPRIVATEFRADATO IS NOT NULL ) -- if @HAEN has a value, @HAENKODEPRIVATEFRADATO must not be null.
			) 
			
		AND 
			(
				-- search with only PNR is OK
				@PNR IS NOT NULL
				OR
				-- If no PNR it must have valid name params for names and birth of date or names and address 
				( 	POSITION('1' in sanitizeForLikeSearchField(@FORNAVNE, @MELLEMNAVNE, @EFTERNAVN, @ADRESSERINGSNAVN),"1") > 0 -- will only contains '1' if a fistname or middlename exists.
					AND	POSITION('2' in sanitizeForLikeSearchField(@FORNAVNE, @MELLEMNAVNE, @EFTERNAVN, @ADRESSERINGSNAVN),"2") > 0 --will only contains '2' if a last name exists.
					AND
						( @FOEDSELSDATO IS NOT NULL AND ISDATE(@FOEDSELSDATO) -- name and foedselsdato/date of birth is OK search PARAMS
						OR  @DARADRESSE IS NOT NULL -- name and daraddress is OK search params
						OR  ( 	(@KOMKOD IS NOT NULL OR @POSTNR IS NOT NULL OR @POSTDISTRIKT IS NOT NULL) -- name and various adress fields is OK search params
								AND	(@VEJKODE IS NOT NULL OR @VEJADRESSERINGSNAVN IS NOT NULL OR @VEJNAVN IS NOT NULL)
								AND	(@HUSNR IS NOT NULL OR @BYGNINGSNUMMER IS NOT NULL) -- see note about @HUSNR which can be the empty string ''. '' is not null!!
							)					
						)
				)
			)
		)
			-- validation end

	/* LEADINGZEROS - functionality shall be added and used for trimming leading zeros from input parameters. 
	   If an input parameter consists only of zeros, the functionality shall replace those with only a single zero. '0000' will end up to be '0'. */

		
		-- search for objects/persons begins (within all person statuses)
		AND	
			(
				(	
					(@HAENPRIVATEFRADATO IS NULL OR Cprhaendelse.rettetden >= @HAENPRIVATEFRADATO)-- FromDate is included
					AND (@HAENPRIVATETILDATO IS NULL OR Cprhaendelse.rettetden < @HAENPRIVATETILDATO) -- ToDate is excluded
					AND	(@HAEN IS NULL OR (Cprhaendelse.forretningshaendelse IN ('ADRESSEOPLYSNINGER_OG_BESKYTTELSE', 'CPRADRESSE', 'KONTAKTADRESSE', 'NAVN_OG_BESKYTTELSE', 'UDREJSEINDREJSE', 'VAERGEMAAL') AND Cprhaendelse.Forretningshaendelse IN (@HAEN))) -- Only a subset of events is available for private companies -- DXC : list created from documentation of data extract for private companies: https://cprservicedesk.atlassian.net/wiki/spaces/CPR/pages/11436049/Udtr+k+til+private+virksomheder
				)
			)
		AND
			(
				(	
					(@HAENKODEPRIVATEFRADATO IS NULL OR Cprhaendelseskode.registreringFra >= @HAENKODEPRIVATEFRADATO)-- FromDate is included
					AND (@HAENKODEPRIVATETILDATO IS NULL OR Cprhaendelseskode.registreringFra < @HAENKODEPRIVATETILDATO) -- ToDate is excluded
					-- Only a subset of events is available for private companies 
					-- Additional information: List created from documentation of data extract for private companies: https://cprservicedesk.atlassian.net/wiki/spaces/CPR/pages/11436049/Udtr+k+til+private+virksomheder
					-- Some of the specified Cprhaendelseskode from documentation (marked with *) are only available for companies specified in CPR Loven Stk. 3. and are not a part of CprPrivateAll. 
					AND	(@HAENKODE IS NULL OR (Cprhaendelseskode.kode IN ('A01', 'A02', 'A03', 'A04', 'A05', 'A06', 'A08', 'A09', 'A10', 'A13', 'A14', 'A15', 'A16', 'A17', 'A21', 
																		  'A24', 'A25', 'A33', 'A34', 'A36', 'A39', 'A40', 'A42', 'A45', 'A47', 'A51', 'A73', 'A74', 'K74', 
																		  'P01', 'P02', 'P03', 'P10', 'P11', 'P31', 'P42', 'P43', 'P45', 'P58') AND Cprhaendelseskode.kode IN (@HAENKODE))) 				)
			)
		AND
			(
				Person.status <> 'nedlagt_person' -- never include a 'nedlagt_person' person
			)
		AND	(@PNR IS NULL OR Personnummer.personnummer in (@PNR)) -- If PNR is used as input param	
		AND	(@FOEDSELSDATO IS NULL OR Person.foedselsdato = @FOEDSELSDATO)
		AND	(@DARADRESSE IS NULL OR CprAdresse.daradresse = @DARADRESSE)
		AND --cprAdresse search (within all address statuses)
			(
				(	-- use either @KOMKOD, @POSTNR or @POSTDISTRIKT. @KOMKOD is more precise than @POSTNR and @POSTNR is more precise than @POSTDISTRIKT
					(@KOMKOD IS NULL OR CprAdresse.cprkommunekode = @KOMKOD)
				OR
					(@POSTNR IS NULL OR CprAdresse.postnummer = @POSTNR)
				OR
					(@POSTDISTRIKT IS NULL OR CprAdresse.postdistrikt = @POSTDISTRIKT)
				)
			AND
				( -- use either @VEJKODE, @VEJADRESSERINGSNAVN or @VEJNAVN. @VEJKODE is more precise than @VEJADRESSERINGSNAVN and @VEJNAVN
					(@VEJKODE IS NULL OR CprAdresse.cprVejkode = @VEJKODE)
				OR
					(@VEJADRESSERINGSNAVN IS NULL OR CprAdresse.vejadresseringsnavn = @VEJADRESSERINGSNAVN)
				OR
					(@VEJNAVN IS NULL OR CprAdresse.vejnavn = @VEJNAVN)
				-- Following check is used to compensate for if the vejnavn has been used instead of vejadresseringsnavn or the other way around.
				OR
					(@VEJNAVN IS NULL OR CprAdresse.vejadresseringsnavn = @VEJNAVN)
				OR
					(@VEJADRESSERINGSNAVN IS NULL OR CprAdresse.vejnavn = @VEJADRESSERINGSNAVN)
				)
			AND	(@HUSNR IS NULL OR CprAdresse.husnummer = @HUSNR) -- LEADINGZEROS on @HUSNR
			AND	(@BYGNININGSNR IS NULL OR CprAdresse.bygningsnummer = @BYGNININGSNR)  -- LEADINGZEROS on @BYGNININGSNR
			AND	(@SIDEDOER IS NULL OR CprAdresse.sidedoer = @SIDEDOER)  -- LEADINGZEROS on @SIDEDOER
			AND	(@ETAGE IS NULL OR CprAdresse.etage = @ETAGE)  -- LEADINGZEROS on @ETAGE
			AND (@SIDEDOER IS NULL OR CprAdresse.sidedoer = @SIDEDOER)
			)	
		AND -- name search (within all name statuses)
			(
			-- @NAVNEEKSAKT, which can be null (=false), true, or false. If true the search is made directly in fornavne, mellemnavn, efternavn and adr.navn without char replacement etc.
			AND ( (@NAVNEEKSAKT IS NOT NULL AND @NAVNEEKSAKT IS TRUE )
					AND (@ADRESERINGSNAVN is null OR Person.Navne.adresseringsnavn=@ADRESERINGSNAVN)
					AND (@FORNAVNE is null OR Person.Navne.fornavne=@FORNAVNE)
					AND (@MELLEMNAVNE is null OR Person.Navne.mellemnavn=@MELLEMNAVNE)
					AND (@EFTERNAVN is null OR Person.Navne.efternavn=@EFTERNAVN)
				)
			AND ( 	((@NAVNEEKSAKT IS NULL OR @NAVNEEKSAKT IS NOT TRUE)
					AND (LEN(sanitizeForLikeSearchField(@FORNAVNE, @MELLEMNAVNE, @EFTERNAVN, @ADRESSERINGSNAVN)) = 0 --name params (except status) must be null or empty strings
					OR Navn.navnesoegning LIKE sanitizeForLikeSearchField(@FORNAVNE, @MELLEMNAVNE, @EFTERNAVN, @ADRESSERINGSNAVN) )  -- See Java inspired pseudocode
					)
				)
			)




	/*[For komplet forretningslogik : Se Bilag 23 - Afsnittet Private Tjenester- Søgning på navne]

	
	See Java inspired pseudocode. Up to DAF vendor how to implementet
	@RETURN A string
	*/
	CREATE FUNCTION sanitizeForLikeSearch(forNavne VARCHAR, mellemNavn VARCHAR, efterNavn VARCHAR, adresseringsNavn VARCHAR)
		-- Java example 
		/*
		Examples of property values and the result returned from sanitizeForLikeSearch method
		
		forNavne                | mellemNavn           	| efterNavn           | adrNavn                                 | resultat
		'Jørgen Hans'          	| 'Åge-Jørgen'          | 'Jørgensen'         | 'Sørgensen, Åge Jørgen'              	| '%1aage1%%1joergen1%%1joergen1%%1hans1%%1aage1%%1joergen1%%2joergensen2%%2soergensen2%'
		'Jørgen Hans'          	| 'Åge-Jørgen'          | 'Jørgensen'         | 'Åge Jørgen Sørgensen'                  | '%1aage1%%1joergen1%%1joergen1%%1hans1%%1aage1%%1joergen1%%2joergensen2%%2soergensen2%'
		'Jørgen Hans'          	| 'Åge-Ørvik'           | 'Jørgensen'         | 'Jørgensen, Jørgen Åge'                 | '%1joergen1%%1aage1%%1joergen1%%1hans1%%1aage1%%1oervik1%%2joergensen2%'
		'Jørgen Hans'          	| 'Åge-Ørvik'           | 'Jørgensen'         | 'Jørgen Åge Jørgensen'                  | '%1joergen1%%1aage1%%1joergen1%%1hans1%%1aage1%%1oervik1%%2joergensen2%'
		'Kristine Mette'      	| 'Kristine Mette'      | 'Henriksen'         | 'Henriksen, Mette-Kristine'             | '%1mette1%%1kristine1%%1kristine1%%1mette1%%1kristine1%%1mette1%%2henriksen2%'
		'Kristine Mette'      	| 'Kristine Mette'      | 'Henriksen'         | 'Mette-Kristine Henriksen'              | '%1mette1%%1kristine1%%1kristine1%%1mette1%%1kristine1%%1mette1%%2henriksen2%'
		'Kristine Mette'      	| 'Nikoline'            | 'Henriksen'         | 'Henriksen,Nikoline M Kristine'       	| '%1nikoline1%%1m1%%1kristine1%%1kristine1%%1mette1%%1nikoline1%%2henriksen2%'
		'Kristine Mette'      	| 'Nikoline'            | 'Henriksen'         | 'Nikoline M Kristine Henriksen'       	| '%1nikoline1%%1m1%%1kristine1%%1kristine1%%1mette1%%1nikoline1%%2henriksen2%'
		'Peter Hans'            | 'Peter Jørgen'        | 'Jørgensen'         | 'Jørgensen, Jørgen Peter'               | '%1joergen1%%1peter1%%1peter1%%1hans1%%1peter1%%1joergen1%%2joergensen2%'
		'Jørgen Hans'          	| 'Jørgen Hansi'        | 'Jørgensen'         | 'Jørgensen, Jørgen'                     | '%1joergen1%%1joergen1%%1hans1%%1joergen1%%1hansi1%%2joergensen2%'
		'Jørgen Hans'          	| 'Jørgen Hansi'       	| 'Jørgensen Sørensen'| 'Jørgensen Sørensen, Jørgen'    		| '%1joergen1%%1joergen1%%1hans1%%1joergen1%%1hansi1%%2joergensen2%%2soerensen2%'
		'Jørgen Hans'          	| 'Jørgen Hansi'       	| 'Jørgensen Sørensen'| ' Sørensen  Jørgensen, Jørgen'    		| '%1joergen1%%1joergen11hans1%%1joergen1%%1hansi1%%2joergensen2%%2soerensen2%%2soerensen2%%2joergensen2%'
		null                    | 'Åge-Ørvik'           | 'Jørgensen'         | 'Jørgensen, Jørgen'                     | '%1joergen1%%1aage1%%1oervik1%%2joergensen2%'   
		null                    | 'Åge-Ørvik'           | 'Jørgensen'         | null                                    | '%1aage1%%1oervik1%%2joergensen2%' 
		'Jørgen Hans'          	| null                  | 'Jørgensen'         | 'Sørgensen, Jørgen'                     | '%1joergen1%%1joergen1%%1hans1%%2joergensen2%%2soergensen2%'
		'Jørgen Hans'          	| 'Åge-Ørvik'           | null                | 'Jørgensen, Jørgen'                     | '%1joergen1%%1joergen1%%1hans1%%1aage1%%1oervik1%%2joergensen2%'
		'Jørgen Hans'          	| 'Åge-Ørvik'           | 'Jørgensen'         | null                                    | '%1joergen1%%1hans1%%1aage1%%1oervik1%%2joergensen2%'
		'Jürgen Jürgen Jürgen'	| 'Jürgen-Jürgen' 		| 'Jürgen'            | 'Jürgen, Jürgen Jürgen'                 | '%1jurgen1%%1jurgen1%%1jurgen1%%1jurgen1%%1jurgen1%%1jurgen1%%1jurgen1%%2jurgen2%'
		'Ælse Øli@'             | 'Åge-Ørvik'           | 'Hansen'            | 'Thorsdottir-Hansen, Ælse Øli@'     	| '%1aelse1%%1oeli1%%1aelse1%%1oeli1%%1aage1%%1oervik1%%2hansen2%%2thorsdottir2%%2hansen2%'
		'Ælse Øli@'             | 'Åge-Ørvik'           | 'Hansen'            | 'Hansen-Thorsdottir, Ælse Øli@'     	| '%1aelse1%%1oeli1%%1aelse1%%1oeli1%%1aage1%%1oervik1%%2hansen2%%2hansen2%%2thorsdottir2%'
		'Gökhan Ķentır'     	| 'Åge-Ørvik-Åge-Ørvik'	| 'Jørgensen'     	  | 'Jørgensen, Jørgen'                     | '%1joergen1%%1gokhan1%%1entr1%%1aage1%%1oervik11aage1%%1oervik1%%2joergensen2%'
		'1111 1111'            	| '1111-1111'           | '2222'              | '22222, 1111 11111'                     | ''
		''                      | 'Kent'                | 'Kkkkenethsen'  	  | 'Kenethsen, Kent'                       | '%1kent1%%1kent1%%2kkkkenethsen2%%2kenethsen2%'
		'Kent'                  | ''                    | 'Kkkkenethsen'      | 'Kenethsen, Kent'                       | '%1kent1%%1kent1%%2kkkkenethsen2%%2kenethsen2%'
		'Kent'                  | 'Kkkkeneth'           | ''                  | 'Kenethsen, Kent'                       | '%1kent1%%1kent1%%1kkkkeneth1%%2kenethsen2%'
		''                      | ''                    | ''                  | ''                                      | ''
		null                    | null                  | null                | null                                    | ''

		*/
		-- Java class with code
		/*
		package com.ja.readtest;

		public class SanitizerDaf {

			public String sanitizeForSearchField(String forNavne, String mellemNavn, String efterNavn,
					String adresseringsNavn) {
				return sanitizeForLikeSearch(forNavne, mellemNavn, efterNavn, adresseringsNavn).replace("%", "");
			}

			public String sanitizeForLikeSearch(String forNavne, String mellemNavn, String efterNavn,
					String adresseringsNavn) {
				forNavne = forNavne == null ? "" : forNavne;
				mellemNavn = mellemNavn == null ? "" : mellemNavn;
				String sanitizedNavn;
				String navne = sanitizeAdresseringsForNavne(adresseringsNavn);
				navne += sanitizeForNavnMellemNavn(forNavne + " " + mellemNavn);
				navne += navne.contains(sanitizedNavn = sanitizeEfterNavn(efterNavn)) ? "" : sanitizedNavn;
				navne += navne.contains(sanitizedNavn = sanitizeAdresseringsEfterNavn(adresseringsNavn)) ? ""
						: sanitizedNavn;
				return navne;
			}

			private String sanitize(String navn) {
				return navn == null ? ""
						: navn.trim().replace('À', 'a').replace('Á', 'a').replace('Â', 'a').replace('Ã', 'a')
								.replace('Ä', 'a').replace("Å", "aa").replace("Æ", "ae").replace('Ç', 'c')
								.replace('È', 'e').replace('É', 'e').replace('Ê', 'e').replace('Ë', 'e')
								.replace('Ì', 'i').replace('Í', 'i').replace('Î', 'i').replace('Ï', 'i')
								.replace('Ð', 'd').replace('Ñ', 'n').replace('Ò', 'o').replace('Ó', 'o')
								.replace('Ô', 'o').replace('Õ', 'o').replace('Ö', 'o').replace("Ø", "oe")
								.replace('Ù', 'u').replace('Ú', 'u').replace('Û', 'u').replace('Ü', 'u')
								.replace('Ý', 'y').replace("Þ", "th").replace("ß", "ss").replace('à', 'a')
								.replace('á', 'a').replace('â', 'a').replace('ã', 'a').replace('ä', 'a')
								.replace("å", "aa").replace("æ", "ae").replace('ç', 'c').replace('è', 'e')
								.replace('é', 'e').replace('ê', 'e').replace('ë', 'e').replace('ì', 'i')
								.replace('í', 'i').replace('î', 'i').replace('ï', 'i').replace('ð', 'o')
								.replace('ñ', 'n').replace('ò', 'o').replace('ó', 'o').replace('ô', 'o')
								.replace('õ', 'o').replace('ö', 'o').replace("ø", "oe").replace('ù', 'u')
								.replace('ú', 'u').replace('û', 'u').replace('ü', 'u').replace('ý', 'y')
								.replace("þ", "th").replace('ÿ', 'y').toLowerCase().replaceAll("[^\\x61-\\x7A]", "");
			}

			private String sanitizeNavn(String navn, String token) {
				if (navn == null) {
					return "";
				}
				String resultName = "";
				String sanitized;

				for (String namePart : navn.split("[ ||-]")) {
					resultName += (sanitized = sanitize(namePart)).isEmpty() ? ""
							: "%" + token + sanitized + token + "%";
				}
				return resultName;

			}

			private String sanitizeForNavnMellemNavn(String navn) {
				return sanitizeNavn(navn, "1");
			}

			private String sanitizeEfterNavn(String navn) {
				return sanitizeNavn(navn, "2");
			}

			private String sanitizeAdresseringsForNavne(String adresseringsNavn) {
				if (adresseringsNavn == null || (adresseringsNavn = adresseringsNavn.trim()).length() < 3) {
					return "";
				}
				// adresseringsNavn is on the form efternavn,fornavne
				int index = adresseringsNavn.indexOf(',');
				if (index > -1) {
					return sanitizeForNavnMellemNavn(adresseringsNavn.substring(index));
				}
				index = adresseringsNavn.lastIndexOf(' ');
				// adresseringsNavn is on the form fornavne efternavn
				if (index > -1) {
					return sanitizeForNavnMellemNavn(adresseringsNavn.substring(0, index));
				}
				return "";
			}

			private String sanitizeAdresseringsEfterNavn(String adresseringsNavn) {
				if (adresseringsNavn == null || (adresseringsNavn = adresseringsNavn.trim()).length() < 3) {
					return "";
				}

				// adresseringsNavn is on the form efternavn,fornavne
				int index = adresseringsNavn.indexOf(',');
				if (index > -1) {
					return sanitizeEfterNavn(adresseringsNavn.substring(0, index));
				}
				index = adresseringsNavn.lastIndexOf(' ');
				// adresseringsNavn is on the form fornavne efternavn
				if (index > -1) {
					return sanitizeEfterNavn(adresseringsNavn.substring(index));
				}
				return "";

			}
		}
		*/

	END


-- NOTE:
--IMPORTANT INFO about objects/persons returned in the resultset.
-- IF @PNR is not null THEN the resultset can contains 1 (one) object/person per distinct and valid personnummer entity in list.
-- IF @PNR is not null THEN the resultset can contains 1 (one) object/person for a personnummer entity with PERSONNUMMER.status = 'historisk' and 1 (one) object/person for a personnummer entity with PERSONNUMMER.status = 'aktuel', if both related personnummer entities are present in the personnummer input list.
-- IF @PNR is null AND other @ search params are not null THEN the resultset must contains max 1 (one) object/person. If the search extract more than 1 object/person, the resultset must contain 0 (zero) objects/persons.
-- IF @PNR is null AND other @ search params are null THEN the resultset must contain 0 (zero) objects/persons.

-- CPR Loven:
/*
§ 38. Aktieselskaber, anpartsselskaber, fonde, virksomheder og andre juridiske personer samt fysiske personer, der driver erhvervsvirksomhed, har ret til efter bestemmelserne i denne paragraf og i § 40 af Indenrigs- og Sundhedsministeriet at få leveret oplysninger i CPR om en større afgrænset kreds af personer, som de pågældende forud har identificeret enkeltvis, jf. stk. 5. For foreninger er det tillige en betingelse, at de har et anerkendelsesværdigt formål.

Stk. 2. Oplysningerne, der kan videregives efter stk. 1, er

1) nuværende navn, medmindre dette er beskyttet, jf. § 28,

2) nuværende adresse, medmindre denne er beskyttet, jf. § 28, og datoen for flytningen hertil,

3) eventuel stilling,

4) eventuel markering af, at den pågældende frabeder sig henvendelser, der sker i markedsføringsøjemed, jf. § 29, stk. 2,

5) eventuel markering af, at vedkommende ønsker at advare mod kreditgivning i vedkommendes navn, jf. § 29, stk. 3,

6) eventuel død, datoen for dødsfaldet og afdødes daværende adresse, medmindre denne er beskyttet, jf. § 28,

7) eventuel forsvinden og datoen herfor,

8) eventuel udrejse og datoen herfor, eventuel ny adresse i udlandet, medmindre denne er beskyttet, jf. § 28, og datoen herfor,

9) eventuel kontaktadresse og datoen herfor og

10) eventuelt værgemål efter værgemålslovens § 6, datoen herfor og værgens navn og adresse eller

11) løbende ændringer i de i nr. 1-10 nævnte data.

Stk. 3. Forsikringsselskaber og pensionskasser omfattet af lov om finansiel virksomhed samt pengeinstitutter ved administration af opsparing i pensionsøjemed i henhold til lov om finansiel virksomhed har ud over oplysningerne i stk. 2 ret til at få leveret oplysninger om civilstand og civilstandsdato bortset fra oplysning om separation samt ved registrering i CPR af vedkommendes død tillige oplysning om navn og adresse på afdødes ægtefælle eller registrerede partner, medmindre der er registreret beskyttelse af navn og adresse efter § 28.

Stk. 4. Kreditoplysningsbureauer, som Datatilsynet har meddelt tilladelse til kreditoplysningsvirksomhed, har ret til at få oplyst navn og adresse fra CPR, uanset om disse er beskyttede efter § 28.

Stk. 5. Identifikationen af de enkelte personer efter stk. 1-4 skal ske ved enten

1) personnummer,

2) fødselsdato og navn (nuværende eller tidligere) eller

3) adresse (nuværende eller tidligere) og navn (nuværende eller tidligere).

Stk. 6. Det er en betingelse for levering af oplysninger efter stk. 1-4, at modtageren efter Europa-Parlamentets og Rådets forordning nr. 2016/679 af 27. april 2016 om beskyttelse af fysiske personer i forbindelse med behandling af personoplysninger og om fri udveksling af sådanne oplysninger og databeskyttelsesloven er berettiget til at behandle oplysningerne.
*/