blob: 07beeac7bd8d51a488b800a94652ebb39700b3e3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.ofbiz.party.party;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletRequest;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilFormatOut;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityConditionList;
import org.apache.ofbiz.entity.condition.EntityExpr;
import org.apache.ofbiz.entity.condition.EntityFunction;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.model.ModelEntity;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
/**
* Worker methods for Party Information
*/
public class PartyWorker {
public static String module = PartyWorker.class.getName();
private PartyWorker() {}
public static Map<String, GenericValue> getPartyOtherValues(ServletRequest request, String partyId, String partyAttr, String personAttr, String partyGroupAttr) {
Delegator delegator = (Delegator) request.getAttribute("delegator");
Map<String, GenericValue> result = new HashMap<String, GenericValue>();
try {
GenericValue party = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();
if (party != null)
result.put(partyAttr, party);
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting Party entity", module);
}
try {
GenericValue person = EntityQuery.use(delegator).from("Person").where("partyId", partyId).queryOne();
if (person != null)
result.put(personAttr, person);
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting Person entity", module);
}
try {
GenericValue partyGroup = EntityQuery.use(delegator).from("PartyGroup").where("partyId", partyId).queryOne();
if (partyGroup != null)
result.put(partyGroupAttr, partyGroup);
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting PartyGroup entity", module);
}
return result;
}
/**
* Generate a sequenced club id using the prefix passed and a sequence value + check digit
* @param delegator used to obtain a sequenced value
* @param prefix prefix inserted at the beginning of the ID
* @param length total length of the ID including prefix and check digit
* @return Sequenced Club ID string with a length as defined starting with the prefix defined
*/
public static String createClubId(Delegator delegator, String prefix, int length) {
final String clubSeqName = "PartyClubSeq";
String clubId = prefix != null ? prefix : "";
// generate the sequenced number and pad
Long seq = delegator.getNextSeqIdLong(clubSeqName);
clubId = clubId + UtilFormatOut.formatPaddedNumber(seq.longValue(), (length - clubId.length() - 1));
// get the check digit
int check = UtilValidate.getLuhnCheckDigit(clubId);
clubId = clubId + Integer.toString(check);
return clubId;
}
public static GenericValue findPartyLatestContactMech(String partyId, String contactMechTypeId, Delegator delegator) {
try {
return EntityQuery.use(delegator).from("PartyAndContactMech")
.where("partyId", partyId, "contactMechTypeId", contactMechTypeId)
.orderBy("-fromDate")
.filterByDate()
.queryFirst();
} catch (GenericEntityException e) {
Debug.logError(e, "Error while finding latest ContactMech for party with ID [" + partyId + "] TYPE [" + contactMechTypeId + "]: " + e.toString(), module);
return null;
}
}
public static GenericValue findPartyLatestPostalAddress(String partyId, Delegator delegator) {
GenericValue pcm = findPartyLatestContactMech(partyId, "POSTAL_ADDRESS", delegator);
if (pcm != null) {
try {
return pcm.getRelatedOne("PostalAddress", false);
} catch (GenericEntityException e) {
Debug.logError(e, "Error while finding latest PostalAddress for party with ID [" + partyId + "]: " + e.toString(), module);
}
}
return null;
}
public static GenericValue findPartyLatestPostalAddressGeoPoint(String partyId, Delegator delegator) {
GenericValue latestPostalAddress = findPartyLatestPostalAddress(partyId, delegator);
if (latestPostalAddress != null) {
try {
GenericValue latestGeoPoint = latestPostalAddress.getRelatedOne("GeoPoint", false);
if (latestGeoPoint != null) {
return latestGeoPoint;
}
return null;
} catch (GenericEntityException e) {
Debug.logError(e, "Error while finding latest GeoPoint for party with ID [" + partyId + "]: " + e.toString(), module);
}
}
return null;
}
public static GenericValue findPartyLatestTelecomNumber(String partyId, Delegator delegator) {
GenericValue pcm = findPartyLatestContactMech(partyId, "TELECOM_NUMBER", delegator);
if (pcm != null) {
try {
return pcm.getRelatedOne("TelecomNumber", false);
} catch (GenericEntityException e) {
Debug.logError(e, "Error while finding latest TelecomNumber for party with ID [" + partyId + "]: " + e.toString(), module);
}
}
return null;
}
public static GenericValue findPartyLatestUserLogin(String partyId, Delegator delegator) {
try {
return EntityQuery.use(delegator).from("UserLogin").where("partyId", partyId).orderBy("-" + ModelEntity.STAMP_FIELD).queryFirst();
} catch (GenericEntityException e) {
Debug.logError(e, "Error while finding latest UserLogin for party with ID [" + partyId + "]: " + e.toString(), module);
return null;
}
}
public static Timestamp findPartyLastLoginTime(String partyId, Delegator delegator) {
try {
GenericValue v = EntityQuery.use(delegator).from("UserLoginHistory").where("partyId", partyId).orderBy("-fromDate").queryFirst();
if (v != null) {
return v.getTimestamp("fromDate");
} else {
return null;
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error while finding latest login time for party with ID [" + partyId + "]: " + e.toString(), module);
return null;
}
}
public static Locale findPartyLastLocale(String partyId, Delegator delegator) {
// just get the most recent UserLogin for this party, if there is one...
GenericValue userLogin = findPartyLatestUserLogin(partyId, delegator);
if (userLogin == null) {
return null;
}
String localeString = userLogin.getString("lastLocale");
if (UtilValidate.isNotEmpty(localeString)) {
return UtilMisc.parseLocale(localeString);
} else {
return null;
}
}
public static String findFirstMatchingPartyId(Delegator delegator, String address1, String address2, String city,
String stateProvinceGeoId, String postalCode, String postalCodeExt, String countryGeoId,
String firstName, String middleName, String lastName) throws GeneralException {
String[] info = findFirstMatchingPartyAndContactMechId(delegator, address1, address2, city, stateProvinceGeoId, postalCode,
postalCodeExt, countryGeoId, firstName, middleName, lastName);
if (info != null) {
return info[0];
}
return null;
}
public static String[] findFirstMatchingPartyAndContactMechId(Delegator delegator, String address1, String address2, String city,
String stateProvinceGeoId, String postalCode, String postalCodeExt, String countryGeoId,
String firstName, String middleName, String lastName) throws GeneralException {
List<GenericValue> matching = findMatchingPersonPostalAddresses(delegator, address1, address2, city, stateProvinceGeoId, postalCode,
postalCodeExt, countryGeoId, firstName, middleName, lastName);
GenericValue v = EntityUtil.getFirst(matching);
if (v != null) {
return new String[] { v.getString("partyId"), v.getString("contactMechId") };
}
return null;
}
/** Finds all matching PartyAndPostalAddress records based on the values provided. Excludes party records with a statusId of PARTY_DISABLED. Results are ordered by descending PartyContactMech.fromDate.
* The matching process is as follows:
* 1. Calls {@link #findMatchingPartyPostalAddress(Delegator, String, String, String, String, String, String, String, String)} to retrieve a list of address matched PartyAndPostalAddress records. Results are limited to Parties of type PERSON.
* 2. For each matching PartyAndPostalAddress record, the Person record for the Party is then retrieved and an upper case comparison is performed against the supplied firstName, lastName and if provided, middleName.
*
* @param delegator Delegator instance
* @param address1 PostalAddress.address1 to match against (Required).
* @param address2 Optional PostalAddress.address2 to match against.
* @param city PostalAddress.city value to match against (Required).
* @param stateProvinceGeoId Optional PostalAddress.stateProvinceGeoId value to match against. If null or "**" is passed then the value will be ignored during matching. "NA" can be passed in place of "_NA_".
* @param postalCode PostalAddress.postalCode value to match against. Cannot be null but can be skipped by passing a value starting with an "*". If the length of the supplied string is 10 characters and the string contains a "-" then the postal code will be split at the "-" and the second half will be used as the postalCodeExt.
* @param postalCodeExt Optional PostalAddress.postalCodeExt value to match against. Will be overridden if a postalCodeExt value is retrieved from postalCode as described above.
* @param countryGeoId Optional PostalAddress.countryGeoId value to match against.
* @param firstName Person.firstName to match against (Required).
* @param middleName Optional Person.middleName to match against.
* @param lastName Person.lastName to match against (Required).
* @return List of PartyAndPostalAddress GenericValue objects that match the supplied criteria.
* @throws GeneralException
*/
public static List<GenericValue> findMatchingPersonPostalAddresses(Delegator delegator, String address1, String address2, String city,
String stateProvinceGeoId, String postalCode, String postalCodeExt, String countryGeoId,
String firstName, String middleName, String lastName) throws GeneralException {
// return list
List<GenericValue> returnList = new LinkedList<GenericValue>();
// address information
if (firstName == null || lastName == null) {
throw new IllegalArgumentException();
}
List<GenericValue> validFound = findMatchingPartyPostalAddress(delegator, address1, address2, city, stateProvinceGeoId, postalCode, postalCodeExt, countryGeoId, "PERSON");
if (UtilValidate.isNotEmpty(validFound)) {
for (GenericValue partyAndAddr: validFound) {
String partyId = partyAndAddr.getString("partyId");
if (UtilValidate.isNotEmpty(partyId)) {
GenericValue p = EntityQuery.use(delegator).from("Person").where("partyId", partyId).queryOne();
if (p != null) {
String fName = p.getString("firstName");
String lName = p.getString("lastName");
String mName = p.getString("middleName");
if (lName.toUpperCase().equals(lastName.toUpperCase())) {
if (fName.toUpperCase().equals(firstName.toUpperCase())) {
if (mName != null && middleName != null) {
if (mName.toUpperCase().equals(middleName.toUpperCase())) {
returnList.add(partyAndAddr);
}
} else if (middleName == null) {
returnList.add(partyAndAddr);
}
}
}
}
}
}
}
return returnList;
}
/**
* @deprecated Renamed to {@link #findMatchingPersonPostalAddresses(Delegator, String, String, String, String, String, String, String, String, String, String)}
*/
@Deprecated
public static List<GenericValue> findMatchingPartyAndPostalAddress(Delegator delegator, String address1, String address2, String city,
String stateProvinceGeoId, String postalCode, String postalCodeExt, String countryGeoId,
String firstName, String middleName, String lastName) throws GeneralException {
return PartyWorker.findMatchingPersonPostalAddresses(delegator, address1, address2, city, stateProvinceGeoId, postalCode, postalCodeExt, countryGeoId, firstName, middleName, lastName);
}
/**
* Finds all matching parties based on the values provided. Excludes party records with a statusId of PARTY_DISABLED. Results are ordered by descending PartyContactMech.fromDate.
* 1. Candidate addresses are found by querying PartyAndPostalAddress using the supplied city and if provided, stateProvinceGeoId, postalCode, postalCodeExt and countryGeoId
* 2. In-memory address line comparisons are then performed against the supplied address1 and if provided, address2. Address lines are compared after the strings have been converted using {@link #makeMatchingString(Delegator, String)}.
*
* @param delegator Delegator instance
* @param address1 PostalAddress.address1 to match against (Required).
* @param address2 Optional PostalAddress.address2 to match against.
* @param city PostalAddress.city value to match against (Required).
* @param stateProvinceGeoId Optional PostalAddress.stateProvinceGeoId value to match against. If null or "**" is passed then the value will be ignored during matching. "NA" can be passed in place of "_NA_".
* @param postalCode PostalAddress.postalCode value to match against. Cannot be null but can be skipped by passing a value starting with an "*". If the length of the supplied string is 10 characters and the string contains a "-" then the postal code will be split at the "-" and the second half will be used as the postalCodeExt.
* @param postalCodeExt Optional PostalAddress.postalCodeExt value to match against. Will be overridden if a postalCodeExt value is retrieved from postalCode as described above.
* @param countryGeoId Optional PostalAddress.countryGeoId value to match against.
* @param partyTypeId Optional Party.partyTypeId to match against.
* @return List of PartyAndPostalAddress GenericValue objects that match the supplied criteria.
* @throws GenericEntityException
*/
public static List<GenericValue> findMatchingPartyPostalAddress(Delegator delegator, String address1, String address2, String city,
String stateProvinceGeoId, String postalCode, String postalCodeExt, String countryGeoId, String partyTypeId) throws GenericEntityException {
if (address1 == null || city == null || postalCode == null) {
throw new IllegalArgumentException();
}
List<EntityCondition> addrExprs = new LinkedList<EntityCondition>();
if (stateProvinceGeoId != null) {
if ("**".equals(stateProvinceGeoId)) {
Debug.logWarning("Illegal state code passed!", module);
} else if ("NA".equals(stateProvinceGeoId)) {
addrExprs.add(EntityCondition.makeCondition("stateProvinceGeoId", EntityOperator.EQUALS, "_NA_"));
} else {
addrExprs.add(EntityCondition.makeCondition("stateProvinceGeoId", EntityOperator.EQUALS, stateProvinceGeoId.toUpperCase()));
}
}
if (!postalCode.startsWith("*")) {
if (postalCode.length() == 10 && postalCode.indexOf("-") != -1) {
String[] zipSplit = postalCode.split("-", 2);
postalCode = zipSplit[0];
postalCodeExt = zipSplit[1];
}
addrExprs.add(EntityCondition.makeCondition("postalCode", EntityOperator.EQUALS, postalCode));
}
if (postalCodeExt != null) {
addrExprs.add(EntityCondition.makeCondition("postalCodeExt", EntityOperator.EQUALS, postalCodeExt));
}
addrExprs.add(EntityCondition.makeCondition(EntityFunction.UPPER_FIELD("city"), EntityOperator.EQUALS, EntityFunction.UPPER(city)));
if (countryGeoId != null) {
addrExprs.add(EntityCondition.makeCondition("countryGeoId", EntityOperator.EQUALS, countryGeoId.toUpperCase()));
}
// limit to only non-disabled status
addrExprs.add(EntityCondition.makeCondition(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, null),
EntityOperator.OR, EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PARTY_DISABLED")));
if (partyTypeId != null) {
addrExprs.add(EntityCondition.makeCondition("partyTypeId", EntityOperator.EQUALS, partyTypeId));
}
List<GenericValue> addresses = EntityQuery.use(delegator).from("PartyAndPostalAddress")
.where(EntityCondition.makeCondition(addrExprs, EntityOperator.AND))
.orderBy("-fromDate")
.filterByDate()
.queryList();
if (UtilValidate.isEmpty(addresses)) {
// No address matches, return an empty list
return addresses;
}
List<GenericValue> validFound = new LinkedList<GenericValue>();
// check the address line
for (GenericValue address: addresses) {
// address 1 field
String addr1Source = PartyWorker.makeMatchingString(delegator, address1);
String addr1Target = PartyWorker.makeMatchingString(delegator, address.getString("address1"));
if (addr1Target != null) {
Debug.logInfo("Comparing address1 : " + addr1Source + " / " + addr1Target, module);
if (addr1Target.equals(addr1Source)) {
// address 2 field
if (address2 != null) {
String addr2Source = PartyWorker.makeMatchingString(delegator, address2);
String addr2Target = PartyWorker.makeMatchingString(delegator, address.getString("address2"));
if (addr2Target != null) {
Debug.logInfo("Comparing address2 : " + addr2Source + " / " + addr2Target, module);
if (addr2Source.equals(addr2Target)) {
Debug.logInfo("Matching address2; adding valid address", module);
validFound.add(address);
}
}
} else {
if (address.get("address2") == null) {
Debug.logInfo("No address2; adding valid address", module);
validFound.add(address);
}
}
}
}
}
return validFound;
}
/**
* Converts the supplied String into a String suitable for address line matching.
* Performs the following transformations on the supplied String:
* - Converts to upper case
* - Retrieves all records from the AddressMatchMap table and replaces all occurrences of addressMatchMap.mapKey with addressMatchMap.mapValue using upper case matching.
* - Removes all non-word characters from the String i.e. everything except A-Z, 0-9 and _
* @param delegator A Delegator instance
* @param address The address String to convert
* @return The converted Address
*/
public static String makeMatchingString(Delegator delegator, String address) {
if (address == null) {
return null;
}
// upper case the address
String str = address.trim().toUpperCase();
// replace mapped words
List<GenericValue> addressMap = null;
try {
addressMap = EntityQuery.use(delegator).from("AddressMatchMap").orderBy("sequenceNum").queryList();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (addressMap != null) {
for (GenericValue v: addressMap) {
str = str.replaceAll(v.getString("mapKey").toUpperCase(), v.getString("mapValue").toUpperCase());
}
}
// remove all non-word characters
return str.replaceAll("\\W", "");
}
public static List<String> getAssociatedPartyIdsByRelationshipType(Delegator delegator, String partyIdFrom, String partyRelationshipTypeId) {
List<GenericValue> partyList = new LinkedList<GenericValue>();
List<String> partyIds = null;
try {
EntityConditionList<EntityExpr> baseExprs = EntityCondition.makeCondition(UtilMisc.toList(
EntityCondition.makeCondition("partyIdFrom", partyIdFrom),
EntityCondition.makeCondition("partyRelationshipTypeId", partyRelationshipTypeId)), EntityOperator.AND);
List<GenericValue> associatedParties = EntityQuery.use(delegator).from("PartyRelationship").where(baseExprs).cache(true).queryList();
partyList.addAll(associatedParties);
while (UtilValidate.isNotEmpty(associatedParties)) {
List<GenericValue> currentAssociatedParties = new LinkedList<GenericValue>();
for (GenericValue associatedParty : associatedParties) {
EntityConditionList<EntityExpr> innerExprs = EntityCondition.makeCondition(UtilMisc.toList(
EntityCondition.makeCondition("partyIdFrom", associatedParty.get("partyIdTo")),
EntityCondition.makeCondition("partyRelationshipTypeId", partyRelationshipTypeId)), EntityOperator.AND);
List<GenericValue> associatedPartiesChilds = EntityQuery.use(delegator).from("PartyRelationship").where(innerExprs).cache(true).queryList();
if (UtilValidate.isNotEmpty(associatedPartiesChilds)) {
currentAssociatedParties.addAll(associatedPartiesChilds);
}
partyList.add(associatedParty);
}
associatedParties = currentAssociatedParties;
}
partyIds = EntityUtil.getFieldListFromEntityList(partyList, "partyIdTo", true);
} catch (GenericEntityException e) {
Debug.logWarning(e, module);
}
return partyIds;
}
/**
* Generic service to find party by id.
* By default return the party find by partyId
* but you can pass searchPartyFirst at false if you want search in partyIdentification before
* or pass searchAllId at true to find apartyuct with this id (party.partyId and partyIdentification.idValue)
* @param delegator the delegator
* @param idToFind the party id to find
* @param partyIdentificationTypeId the party identification type id to use
* @param searchPartyFirst search first with party id
* @param searchAllId search all the party ids
* @return returns the parties founds
* @throws GenericEntityException
*/
public static List<GenericValue> findPartiesById(Delegator delegator,
String idToFind, String partyIdentificationTypeId,
boolean searchPartyFirst, boolean searchAllId) throws GenericEntityException {
if (Debug.verboseOn()) Debug.logVerbose("Analyze partyIdentification: entered id = " + idToFind + ", partyIdentificationTypeId = " + partyIdentificationTypeId, module);
GenericValue party = null;
List<GenericValue> partiesFound = null;
// 1) look if the idToFind given is a real partyId
if (searchPartyFirst) {
party = EntityQuery.use(delegator).from("Party").where("partyId", idToFind).cache().queryOne();
}
if (searchAllId || (searchPartyFirst && UtilValidate.isEmpty(party))) {
// 2) Retrieve party in PartyIdentification
Map<String, String> conditions = UtilMisc.toMap("idValue", idToFind);
if (UtilValidate.isNotEmpty(partyIdentificationTypeId)) {
conditions.put("partyIdentificationTypeId", partyIdentificationTypeId);
}
partiesFound = EntityQuery.use(delegator).from("PartyIdentificationAndParty").where(conditions).orderBy("partyId").cache(true).queryList();
}
if (! searchPartyFirst) {
party = EntityQuery.use(delegator).from("Party").where("partyId", idToFind).cache().queryOne();
}
if (party != null) {
if (UtilValidate.isNotEmpty(partiesFound)) partiesFound.add(party);
else partiesFound = UtilMisc.toList(party);
}
if (Debug.verboseOn()) Debug.logVerbose("Analyze partyIdentification: found party.partyId = " + party + ", and list : " + partiesFound, module);
return partiesFound;
}
public static List<GenericValue> findPartiesById(Delegator delegator, String idToFind, String partyIdentificationTypeId)
throws GenericEntityException {
return findPartiesById(delegator, idToFind, partyIdentificationTypeId, true, false);
}
public static String findPartyId(Delegator delegator, String idToFind, String partyIdentificationTypeId) throws GenericEntityException {
GenericValue party = findParty(delegator, idToFind, partyIdentificationTypeId);
if (party != null) {
return party.getString("partyId");
} else {
return null;
}
}
public static String findPartyId(Delegator delegator, String idToFind) throws GenericEntityException {
return findPartyId(delegator, idToFind, null);
}
public static GenericValue findParty(Delegator delegator, String idToFind, String partyIdentificationTypeId) throws GenericEntityException {
List<GenericValue> parties = findPartiesById(delegator, idToFind, partyIdentificationTypeId);
GenericValue party = EntityUtil.getFirst(parties);
return party;
}
public static List<GenericValue> findParties(Delegator delegator, String idToFind, String partyIdentificationTypeId) throws GenericEntityException {
List<GenericValue> partiesByIds = findPartiesById(delegator, idToFind, partyIdentificationTypeId);
List<GenericValue> parties = null;
if (UtilValidate.isNotEmpty(partiesByIds)) {
for (GenericValue party : partiesByIds) {
GenericValue partyToAdd = party;
//retreive party GV if the actual genericValue came from viewEntity
if (! "Party".equals(party.getEntityName())) {
partyToAdd = EntityQuery.use(delegator).from("Party").where("partyId", party.get("partyId")).cache().queryOne();
}
if (UtilValidate.isEmpty(parties)) {
parties = UtilMisc.toList(partyToAdd);
}
else {
parties.add(partyToAdd);
}
}
}
return parties;
}
public static List<GenericValue> findParties(Delegator delegator, String idToFind) throws GenericEntityException {
return findParties(delegator, idToFind, null);
}
public static GenericValue findParty(Delegator delegator, String idToFind) throws GenericEntityException {
return findParty(delegator, idToFind, null);
}
}