We have the opportunity to init jaxb context from external oxm file
Map<String, Object> props = new HashMap<String, Object>(1);
props.put(JAXBContextProperties.OXM_METADATA_SOURCE, "oxm.xml");
JAXBContext jc = JAXBContextFactory.createContext(new Class[0], props, <ClassLoader>);
Can we safe current jaxb context xml bindings to xml? From context inited from jaxb annotated classes (I have jaxb.properties)
JAXBContext jc = JAXBContext.newInstance(new Class[]{...});
Like I save generated schema to file
jc.generateSchema(new SchemaOutputResolver(){...});
I need to write oxm file of my schema with only difference in date/time representation.
I create function to create oxm from package. It is not complete, but do everything that I needed, and good as starting point...
public static void createOXM(Package pack, String filename)
throws Exception
{
/*
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="eclipselink_oxm_2_4.xsd"
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="<name>"
xml-mapping-metadata-complete="true" xml-accessor-type="NONE" xml-accessor-order="UNDEFINED">
*/
org.eclipse.persistence.jaxb.xmlmodel.XmlBindings bindings =
new org.eclipse.persistence.jaxb.xmlmodel.XmlBindings();
bindings.setPackageName(pack.getName());
bindings.setXmlMappingMetadataComplete(true);
bindings.setXmlAccessorType(org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType.NONE);
bindings.setXmlAccessorOrder(org.eclipse.persistence.jaxb.xmlmodel.XmlAccessOrder.UNDEFINED);
List<Class<?>> classes = getClassesForPackage(pack);
for (Class<?> cls: classes)
{
int clsMod = cls.getModifiers();
String clsName = cls.getName().replaceAll("[^\\.]+\\.", "");
if (cls.isAnonymousClass() || !Modifier.isPublic(clsMod)) // Class$1 etc...
continue;
if (cls.getAnnotation(XmlTransient.class) != null)
continue;
org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes javaTypes = bindings.getJavaTypes();
if (javaTypes == null)
{
javaTypes = new org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes();
bindings.setJavaTypes(javaTypes);
}
org.eclipse.persistence.jaxb.xmlmodel.JavaType javaType = new org.eclipse.persistence.jaxb.xmlmodel.JavaType();
javaTypes.getJavaType().add(javaType);
javaType.setName(clsName);
XmlRootElement xmlRoot = cls.getAnnotation(XmlRootElement.class);
if (xmlRoot != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement root =
new org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement();
javaType.setXmlRootElement(root);
if (!"##default".equals(xmlRoot.name()))
root.setName(xmlRoot.name());
if (!"##default".equals(xmlRoot.namespace()))
root.setNamespace(xmlRoot.namespace());
}
XmlType xmlType = cls.getAnnotation(XmlType.class);
if (xmlType != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlType type = new org.eclipse.persistence.jaxb.xmlmodel.XmlType();
javaType.setXmlType(type);
if (!"##default".equals(xmlType.name()))
type.setName(xmlType.name());
if (!"##default".equals(xmlType.namespace()))
type.setNamespace(xmlType.namespace());
String[] props = xmlType.propOrder();
if (props != null && props.length > 0)
{
for (String prop: props)
if (!prop.trim().isEmpty())
type.getPropOrder().add(prop.trim());
}
}
XmlAccessorType xmlAccType = cls.getAnnotation(XmlAccessorType.class);
if (xmlAccType != null)
{
String accType = xmlAccType.value().name();
javaType.setXmlAccessorType(org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType.valueOf(accType));
}
if (cls.isEnum())
{
org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.XmlEnums enums = bindings.getXmlEnums();
if (enums == null)
{
enums = new org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.XmlEnums();
bindings.setXmlEnums(enums);
}
org.eclipse.persistence.jaxb.xmlmodel.XmlEnum en = new org.eclipse.persistence.jaxb.xmlmodel.XmlEnum();
en.setJavaEnum(clsName);
enums.getXmlEnum().add(en);
XmlEnum xmlEnum = cls.getAnnotation(XmlEnum.class);
if (xmlEnum != null)
{
Class<?> xmlClass = xmlEnum.value();
if (xmlClass != String.class)
en.setValue(xmlClass.getName());
}
for (Field field: cls.getDeclaredFields())
if (field.isEnumConstant())
{
org.eclipse.persistence.jaxb.xmlmodel.XmlEnumValue value =
new org.eclipse.persistence.jaxb.xmlmodel.XmlEnumValue();
en.getXmlEnumValue().add(value);
value.setJavaEnumValue(field.getName());
value.setValue(field.getName());
XmlEnumValue enumValue = field.getAnnotation(XmlEnumValue.class);
if (enumValue != null)
value.setValue(enumValue.value());
}
continue;
}
Class clsSuper = cls.getSuperclass();
if (clsSuper.getPackage() == pack)
javaType.setSuperType(clsSuper.getName());
for (Field field: cls.getDeclaredFields())
{
org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes javaAttrs = javaType.getJavaAttributes();
if (javaAttrs == null)
{
javaAttrs = new org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes();
javaType.setJavaAttributes(javaAttrs);
}
XmlTransient xmlTrans = field.getAnnotation(XmlTransient.class);
if (xmlTrans != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlTransient attr =
new org.eclipse.persistence.jaxb.xmlmodel.XmlTransient();
attr.setJavaAttribute(field.getName());
javaAttrs.getJavaAttribute().add(new JAXBElement(new QName("", "xml-transient"), attr.getClass(), attr));
continue;
}
XmlValue xmlValue = field.getAnnotation(XmlValue.class);
if (xmlValue != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlValue attr = new org.eclipse.persistence.jaxb.xmlmodel.XmlValue();
attr.setJavaAttribute(field.getName());
javaAttrs.getJavaAttribute().add(new JAXBElement(new QName("", "xml-value"), attr.getClass(), attr));
continue;
}
XmlAttribute xmlAttr = field.getAnnotation(XmlAttribute.class);
if (xmlAttr != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlAttribute attr =
new org.eclipse.persistence.jaxb.xmlmodel.XmlAttribute();
attr.setJavaAttribute(field.getName());
if (!"##default".equals(xmlAttr.name()) && !field.getName().equals(xmlAttr.name()))
attr.setName(xmlAttr.name());
if (!"##default".equals(xmlAttr.namespace()))
attr.setNamespace(xmlAttr.namespace());
if (xmlAttr.required())
attr.setRequired(true);
XmlSchemaType xmlSchemaType = field.getAnnotation(XmlSchemaType.class);
if (xmlSchemaType != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaType schemaType =
new org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaType();
attr.setXmlSchemaType(schemaType);
schemaType.setName(xmlSchemaType.name());
if (!"http://www.w3.org/2001/XMLSchema".equals(xmlSchemaType.namespace()))
schemaType.setName(xmlSchemaType.namespace());
if (xmlSchemaType.type() != XmlSchemaType.DEFAULT.class)
schemaType.setType(xmlSchemaType.type().getName());
}
XmlJavaTypeAdapter xmlJavaTypeAdapter = field.getAnnotation(XmlJavaTypeAdapter.class);
if (xmlJavaTypeAdapter != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter javaTypeAdapter =
new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
attr.setXmlJavaTypeAdapter(javaTypeAdapter);
if (xmlJavaTypeAdapter.value() != null)
javaTypeAdapter.setValue(xmlJavaTypeAdapter.value().getName());
if (xmlJavaTypeAdapter.type() != XmlJavaTypeAdapter.DEFAULT.class)
javaTypeAdapter.setValue(xmlJavaTypeAdapter.type().getName());
}
javaAttrs.getJavaAttribute().add(new JAXBElement(new QName("", "xml-attribute"), attr.getClass(), attr));
continue;
}
XmlElement xmlElem = field.getAnnotation(XmlElement.class);
if (xmlElem != null && xmlAttr != null)
throw new RuntimeException("XmlAttribute and XmlElement can be both");
org.eclipse.persistence.jaxb.xmlmodel.XmlElement attr = new org.eclipse.persistence.jaxb.xmlmodel.XmlElement();
attr.setJavaAttribute(field.getName());
if (xmlElem != null)
{
if (!"##default".equals(xmlElem.name()) && !field.getName().equals(xmlElem.name()))
attr.setName(xmlElem.name());
if (!"##default".equals(xmlElem.namespace()))
attr.setNamespace(xmlElem.namespace());
if (!"\u0000".equals(xmlElem.defaultValue()))
attr.setDefaultValue(xmlElem.defaultValue());
if (xmlElem.required())
attr.setRequired(true);
if (xmlElem.nillable())
attr.setNillable(true);
}
XmlElementWrapper xmlWrapper = field.getAnnotation(XmlElementWrapper.class);
if (xmlWrapper != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper elemWrapper =
new org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper();
attr.setXmlElementWrapper(elemWrapper);
if (!"##default".equals(xmlWrapper.name()))
elemWrapper.setName(xmlWrapper.name());
if (!"##default".equals(xmlWrapper.namespace()))
elemWrapper.setNamespace(xmlWrapper.namespace());
if (xmlWrapper.required())
elemWrapper.setRequired(true);
if (xmlWrapper.nillable())
elemWrapper.setNillable(true);
}
XmlSchemaType xmlSchemaType = field.getAnnotation(XmlSchemaType.class);
if (xmlSchemaType != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaType schemaType =
new org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaType();
attr.setXmlSchemaType(schemaType);
schemaType.setName(xmlSchemaType.name());
if (!"http://www.w3.org/2001/XMLSchema".equals(xmlSchemaType.namespace()))
schemaType.setName(xmlSchemaType.namespace());
if (xmlSchemaType.type() != XmlSchemaType.DEFAULT.class)
schemaType.setType(xmlSchemaType.type().getName());
}
XmlJavaTypeAdapter xmlJavaTypeAdapter = field.getAnnotation(XmlJavaTypeAdapter.class);
if (xmlJavaTypeAdapter != null)
{
org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter javaTypeAdapter =
new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
attr.setXmlJavaTypeAdapter(javaTypeAdapter);
if (xmlJavaTypeAdapter.value() != null)
javaTypeAdapter.setValue(xmlJavaTypeAdapter.value().getName());
if (xmlJavaTypeAdapter.type() != XmlJavaTypeAdapter.DEFAULT.class)
javaTypeAdapter.setValue(xmlJavaTypeAdapter.type().getName());
}
javaAttrs.getJavaAttribute().add(new JAXBElement(new QName("", "xml-element"), attr.getClass(), attr));
}
}
JAXBContext jc = JAXBContext.newInstance(bindings.getClass());
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
m.setProperty(Marshaller.JAXB_FRAGMENT, false);
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(bindings, new File(filename));
}
Have fun!
Related
We have created some customized reports and these will open up based on Sales Order type in details tab. Same way we want to send report based on order type when we use Email Invoice/Memo action from Actions menu.
We tried to override the code but still we are seeing default report is sent in email. How can I fix this? My code is below:
[PXOverride]
public PXAction<ARInvoice> sendARInvoiceMemo;
[PXUIField(DisplayName = "Send AR Invoice/Memo", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXLookupButton]
public IEnumerable SendARInvoiceMemo(PXAdapter adapter, String reportID)
{
PXReportRequiredException ex = null;
foreach (ARInvoice doc in adapter.Get<ARInvoice>())
{
var parameters = new Dictionary<string, string>();
ARTran TranData = PXSelectReadonly<ARTran, Where<ARTran.tranType, Equal<Required<ARTran.tranType>>,
And<ARTran.refNbr, Equal<Required<ARTran.refNbr>>>>>.Select(Base, doc.DocType, doc.RefNbr);
if (TranData != null)
{
if (TranData.SOOrderType == "WS" || TranData.SOOrderType == "WO" || TranData.SOOrderType == "TS" || TranData.SOOrderType == "IM")
{
if (reportID == null) reportID = "KR501011";
Dictionary<string, string> mailParams = new Dictionary<string, string>();
if (reportID == "KR501011")
{
mailParams["DocType"] = doc.DocType;
mailParams["RefNbr"] = doc.RefNbr;
if (!ReportNotificationGenerator.Send(reportID, mailParams).Any())
{
throw new PXException(ErrorMessages.MailSendFailed);
}
}
Base.Clear();
Base.Document.Current = Base.Document.Search<ARInvoice.refNbr>(doc.RefNbr, doc.DocType);
}
if (TranData.SOOrderType == "RS" || TranData.SOOrderType == "RO" || TranData.SOOrderType == "PS" || TranData.SOOrderType == "QT")
{
if (reportID == null) reportID = "KR501012";
Dictionary<string, string> mailParams = new Dictionary<string, string>();
if (reportID == "KR501012")
{
mailParams["DocType"] = doc.DocType;
mailParams["RefNbr"] = doc.RefNbr;
if (!ReportNotificationGenerator.Send(reportID, mailParams).Any())
{
throw new PXException(ErrorMessages.MailSendFailed);
}
}
Base.Clear();
Base.Document.Current = Base.Document.Search<ARInvoice.refNbr>(doc.RefNbr, doc.DocType);
}
}
}
if (ex != null) throw ex;
return adapter.Get();
}
Note, no version was specified so my work was done against 2020r2.
SendARInvoiceMemo isn't called by the "Email Invoice/Memo" action. Rather, Notification is the delegate for that action.
Note that notification isn't actually calling a report ID, rather it relies on notification CD and your mailing settings to determine what report to run. I modified the code to change to a new notificationCD I created called INVOICEALT. This is configured to my alternative Report ID.
[PXOverride()]
[PXUIField(DisplayName = "Notifications", Visible = false)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntryF)]
public virtual IEnumerable Notification(PXAdapter adapter,
[PXString]
string notificationCD)
{
foreach (ARInvoice doc in adapter.Get().RowCast<ARInvoice>())
{
Base.Document.Current = doc;
Dictionary<string, string> parameters = new Dictionary<string, string>
{
["DocType"] = doc.DocType,
["RefNbr"] = doc.RefNbr
};
using (var ts = new PXTransactionScope())
{
if (ProjectDefaultAttribute.IsProject(Base, doc.ProjectID) && Base.Activity.IsProjectSourceActive(doc.ProjectID, notificationCD))
{
Base.Activity.SendNotification(PMNotificationSource.Project, notificationCD, doc.BranchID, parameters);
}
else
{
//Base.Activity.SendNotification(ARNotificationSource.Customer, notificationCD, doc.BranchID, parameters); //This is what was there
//Inserted switch based on Sales Order Type >>
ARTran TranData = PXSelectReadonly<ARTran, Where<ARTran.tranType, Equal<Required<ARTran.tranType>>,
And<ARTran.refNbr, Equal<Required<ARTran.refNbr>>>>>.Select(Base, doc.DocType, doc.RefNbr);
switch (TranData.SOOrderType)
{
case "IN":
Base.Activity.SendNotification(ARNotificationSource.Customer, "INVOICEALT", doc.BranchID, parameters);
break;
default:
Base.Activity.SendNotification(ARNotificationSource.Customer, notificationCD, doc.BranchID, parameters);
break;
}
//<< Inserted switch based on Sales Order Type
}
Base.Save.Press();
ts.Complete();
}
yield return doc;
}
}
As an alternative to the above, if you're just talking about users running the action, you could hide the Email Invoice/Memo action and put a new action in place.
public PXAction<ARInvoice> sendARInvoiceMemoAlt;
[PXUIField(DisplayName = "Alt Email Invoice/Memo", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXLookupButton]
public IEnumerable SendARInvoiceMemoAlt(PXAdapter adapter, String reportID)
{
PXReportRequiredException ex = null;
foreach (ARInvoice doc in adapter.Get<ARInvoice>())
{
var parameters = new Dictionary<string, string>();
ARTran TranData = PXSelectReadonly<ARTran, Where<ARTran.tranType, Equal<Required<ARTran.tranType>>,
And<ARTran.refNbr, Equal<Required<ARTran.refNbr>>>>>.Select(Base, doc.DocType, doc.RefNbr);
if (TranData != null)
{
if (TranData.SOOrderType == "SO")// || TranData.SOOrderType == "WS" || TranData.SOOrderType == "WO" || TranData.SOOrderType == "TS" || TranData.SOOrderType == "IM")
{
if (reportID == null) reportID = "AR641000";
Dictionary<string, string> mailParams = new Dictionary<string, string>();
if (reportID == "AR641000")
{
mailParams["DocType"] = doc.DocType;
mailParams["RefNbr"] = doc.RefNbr;
if (!ReportNotificationGenerator.Send(reportID, mailParams).Any())
{
throw new PXException(ErrorMessages.MailSendFailed);
}
}
Base.Clear();
Base.Document.Current = Base.Document.Search<ARInvoice.refNbr>(doc.RefNbr, doc.DocType);
}
if (TranData.SOOrderType == "IN")// || TranData.SOOrderType == "RS" || TranData.SOOrderType == "RO" || TranData.SOOrderType == "PS" || TranData.SOOrderType == "QT")
{
if (reportID == null) reportID = "AR641001";
Dictionary<string, string> mailParams = new Dictionary<string, string>();
if (reportID == "AR641001")
{
mailParams["DocType"] = doc.DocType;
mailParams["RefNbr"] = doc.RefNbr;
if (!ReportNotificationGenerator.Send(reportID, mailParams).Any())
{
throw new PXException(ErrorMessages.MailSendFailed);
}
}
Base.Clear();
Base.Document.Current = Base.Document.Search<ARInvoice.refNbr>(doc.RefNbr, doc.DocType);
}
}
}
if (ex != null) throw ex;
return adapter.Get();
}
public override void Initialize()
{
base.Initialize();
Base.ActionsMenuItem.AddMenuAction(sendARInvoiceMemoAlt);
}
After I customized the code below and I want to update SLA by AssignDateTime. But with the Severity changed then my SLA has changed to get datetime from createdDateTime also. I think it should have other event that need to customize.
protected virtual void CRCase_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
if (InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = e.Row as CRCase;
var oldRow = e.OldRow as CRCase;
CRCaseExt rowExt = PXCache<CRCase>.GetExtension<CRCaseExt>(row);
if (row == null || oldRow == null) return;
if (row.OwnerID == null)
{
row.AssignDate = null;
row.SLAETA = null;
}
else if (oldRow.OwnerID == null)
{
row.AssignDate = PXTimeZoneInfo.Now;
if (row == null || row.AssignDate == null) return;
if (row.ClassID != null && row.Severity != null)
{
var severity = (CRClassSeverityTime)PXSelect<CRClassSeverityTime,
Where<CRClassSeverityTime.caseClassID, Equal<Required<CRClassSeverityTime.caseClassID>>,
And<CRClassSeverityTime.severity, Equal<Required<CRClassSeverityTime.severity>>>>>
.Select(Base, row.ClassID, row.Severity);
if (severity != null && severity.TimeReaction != null)
{
row.SLAETA = ((DateTime)row.AssignDate).AddMinutes((int)severity.TimeReaction);
}
}
if (row.Severity != null && row.ContractID != null)
{
var template = (Contract)PXSelect<Contract, Where<Contract.contractID, Equal<Required<CRCase.contractID>>>>.Select(Base, row.ContractID);
if (template == null) return;
var sla = (ContractSLAMapping)PXSelect<ContractSLAMapping,
Where<ContractSLAMapping.severity, Equal<Required<CRCase.severity>>,
And<ContractSLAMapping.contractID, Equal<Required<CRCase.contractID>>>>>
.Select(Base, row.Severity, template.TemplateID);
if (sla != null && sla.Period != null)
{
row.SLAETA = ((DateTime)row.AssignDate).AddMinutes((int)sla.Period);
}
}
}
}
SLAETA field is decorated with PXFormulaAttribute to raise FieldDefaulting event every time change is made to one of the following fields:
CRCase.contractID
CRCase.severity
CRCase.caseClassID
public partial class CRCase : IBqlTable, IAssign, IAttributeSupport, IPXSelectable
{
...
#region SLAETA
public abstract class sLAETA : IBqlField { }
[PXDBDate(PreserveTime = true, DisplayMask = "g")]
[PXUIField(DisplayName = "SLA")]
[PXFormula(typeof(Default<CRCase.contractID, CRCase.severity, CRCase.caseClassID>))]
public virtual DateTime? SLAETA { get; set; }
#endregion
...
}
It’s a way better to only customize CRCase_SLAETA_FieldDefaulting handler in the CRCaseMaint BLC extension instead of implementing CRCase_RowUpdated:
public class CRCaseMaint : PXGraph<CRCaseMaint, CRCase>
{
...
protected virtual void CRCase_SLAETA_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
{
CRCase row = e.Row as CRCase;
if (row == null || row.CreatedDateTime == null) return;
if (row.ClassID != null && row.Severity != null)
{
var severity = (CRClassSeverityTime)PXSelect<CRClassSeverityTime,
Where<CRClassSeverityTime.caseClassID, Equal<Required<CRClassSeverityTime.caseClassID>>,
And<CRClassSeverityTime.severity, Equal<Required<CRClassSeverityTime.severity>>>>>.
Select(this, row.ClassID, row.Severity);
if (severity != null && severity.TimeReaction != null)
{
e.NewValue = ((DateTime)row.CreatedDateTime).AddMinutes((int)severity.TimeReaction);
e.Cancel = true;
}
}
if (row.Severity != null && row.ContractID != null)
{
var template = (Contract)PXSelect<Contract, Where<Contract.contractID, Equal<Required<CRCase.contractID>>>>.Select(this, row.ContractID);
if (template == null) return;
var sla = (ContractSLAMapping)PXSelect<ContractSLAMapping,
Where<ContractSLAMapping.severity, Equal<Required<CRCase.severity>>,
And<ContractSLAMapping.contractID, Equal<Required<CRCase.contractID>>>>>.
Select(this, row.Severity, template.TemplateID);
if (sla != null && sla.Period != null)
{
e.NewValue = ((DateTime)row.CreatedDateTime).AddMinutes((int)sla.Period);
e.Cancel = true;
}
}
}
...
}
You can either use the FieldUpdated Event or in the row updated event you can look for the change of your field.
Eg: row.Severity != oldRow.Severity
I use the fallowing method to update a contact in Exchange over EWS:
private void UpdateContact(Microsoft.Exchange.WebServices.Data.Contact exContact, ContactInfo contact) {
var pathList = new List<string>();
try {
log.DebugFormat("Process ExchangeContact '{0}' with Contact '{1}'", (exContact.IsNew ? "<new>" : exContact.DisplayName), contact.Id);
exContact.GivenName = contact.AdditionalName;
exContact.Surname = contact.Name;
exContact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;
exContact.CompanyName = "";
if (contact is PersonInfo) {
var person = (PersonInfo) contact;
if (person.PersonCompany != null && person.PersonCompany.Company != null) {
exContact.CompanyName = person.PersonCompany.Company.DisplayName;
}
exContact.ImAddresses[ImAddressKey.ImAddress1] = person.MessengerName;
exContact.ImAddresses[ImAddressKey.ImAddress2] = person.SkypeName;
}
// Specify the business, home, and car phone numbers.
var comm = contact.GetCommunication(Constants.CommunicationType.PhoneBusiness);
exContact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = (comm != null ? comm.Value : null);
comm = contact.GetCommunication(Constants.CommunicationType.PhonePrivate);
exContact.PhoneNumbers[PhoneNumberKey.HomePhone] = (comm != null ? comm.Value : null);
comm = contact.GetCommunication(Constants.CommunicationType.PhoneMobile);
exContact.PhoneNumbers[PhoneNumberKey.MobilePhone] = (comm != null ? comm.Value : null);
comm = contact.GetCommunication(Constants.CommunicationType.MailBusiness);
exContact.EmailAddresses[EmailAddressKey.EmailAddress1] = (comm != null ? new EmailAddress(comm.Value) : null);
comm = contact.GetCommunication(Constants.CommunicationType.MailPrivate);
exContact.EmailAddresses[EmailAddressKey.EmailAddress2] = (comm != null ? new EmailAddress(comm.Value) : null);
// Specify two IM addresses.
// Specify the home address.
var address = contact.AddressList.FirstOrDefault(x => x.AddressType != null && x.AddressType.Id == Constants.AddressType.Private);
if (address != null) {
var paEntry = new PhysicalAddressEntry
{
Street = address.Street,
City = address.City,
State = address.Region,
PostalCode = address.PostalCode,
CountryOrRegion = address.CountryName
};
exContact.PhysicalAddresses[PhysicalAddressKey.Home] = paEntry;
if (contact.PostalAddress == address) {
exContact.PostalAddressIndex = PhysicalAddressIndex.Home;
}
} else {
exContact.PhysicalAddresses[PhysicalAddressKey.Home] = null;
}
address = contact.AddressList.FirstOrDefault(x => x.AddressType != null && x.AddressType.Id == Constants.AddressType.Business);
if (address != null) {
var paEntry = new PhysicalAddressEntry
{
Street = address.Street,
City = address.City,
State = address.Region,
PostalCode = address.PostalCode,
CountryOrRegion = address.CountryName
};
exContact.PhysicalAddresses[PhysicalAddressKey.Business] = paEntry;
if(contact.PostalAddress == address) {
exContact.PostalAddressIndex = PhysicalAddressIndex.Business;
}
} else {
exContact.PhysicalAddresses[PhysicalAddressKey.Business] = null;
}
// Save the contact.
if (exContact.IsNew) {
exContact.Save();
} else {
exContact.Update(ConflictResolutionMode.AlwaysOverwrite);
}
pathList.AddRange(this.AddFileAttachments(this.Access.IndependService.GetContact(exContact.Id.UniqueId), contact.GetDocuments()));
} catch(Exception e) {
log.Error("Error updating/inserting Contact in Exchange.", e);
} finally {
foreach (var path in pathList) {
this.Access.Context.Container.Resolve<IDocumentService>().UndoCheckOut(path);
}
}
}
When I do this for update, I get an Exception with Errorcode ErrorIncorrectUpdatePropertyCount on the line exContact.Update(ConflictResolutionMode.AlwaysOverwrite);
Can someone help me, what is the problem? - Thanks.
The solution is that I have to check, if the string-values are empty strings and in this case to set null. On this way, all is working.
I am working on a method that compares two objects using reflection. The object types are objects created from entity framework. When I use GetProperties() I am getting EntityCollection and EntityReference properties. I only want the properties that belong to the object and not any associated properties or references from foreign keys.
I've tried the following How to get all names of properties in an Entity?.
I thought about passing an array of properties to compare but I don't want to have to type them in for each object type. I am open to some suggestions even those that don't use reflection.
public bool CompareEntities<T>(T oldEntity, T newEntity)
{
bool same = true;
PropertyInfo[] properties = oldEntity.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
var oldValue = property.GetValue(oldEntity, null);
var newValue = property.GetValue(newEntity, null);
if (oldValue != null && newValue != null)
{
if (!oldValue.Equals(newValue))
{
same = false;
break;
}
}
else if ((oldValue == null && newValue != null) || (oldValue != null && newValue == null))
{
same = false;
break;
}
}
return same;
}
Using the suggestions from #Eranga and https://stackoverflow.com/a/5381986/1129035 I was able to come up with a workable solution.
Since some of the properties in the root object are a GenericType there needs to be two different if statements. Only if the current property is an EntityCollection skip over it.
public bool CompareEntities<T>(T oldEntity, T newEntity)
{
bool same = true;
PropertyInfo[] properties = oldEntity.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
.Where(pi => !(pi.PropertyType.IsSubclassOf(typeof(EntityObject)))
&& !(pi.PropertyType.IsSubclassOf(typeof(EntityReference)))
).ToArray();
foreach (PropertyInfo property in properties)
{
if (property.PropertyType.IsGenericType)
{
if (property.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>))
{
continue;
}
}
var oldValue = property.GetValue(oldEntity, null);
var newValue = property.GetValue(newEntity, null);
if (oldValue != null && newValue != null)
{
if (!oldValue.Equals(newValue))
{
same = false;
break;
}
}
else if ((oldValue == null && newValue != null) || (oldValue != null && newValue == null))
{
same = false;
break;
}
}
return same;
}
Try filtering out EntityObject type and EntityCollection properties.
var properties = oldEntity.GetType().GetProperties().
Where(pi => !(pi.PropertyType.IsSubclassOf(typeof(EntityObject))
|| pi.PropertyType.IsSubclassOf(typeof(EntityCollection));
make it easy for yourself and do this instead
PropertyInfo[] properties = oldEntity.GetType().GetProperties(pi=> pi.PropertyType.NameSpace=="System").ToArray();
This code works fine on SonyEricsson and Motorola cellphones, but on Nokia it either fails at the beginnig not making any request at all or returns empty response, depending on model.
HttpConnection hc = null;
InputStream is = null;
InputStreamReader isr = null;
String result = "";
try
{
hc = (HttpConnection) Connector.open(url);
int rc = hc.getResponseCode();
if (rc != HttpConnection.HTTP_OK)
{
throw new IOException(hc.getResponseMessage());
}
is = hc.openInputStream();
isr = new InputStreamReader(is, "utf-8");
int ch;
while ((ch = is.read()) != -1)
{
result += (char) ch;
}
}
finally
{
if (is != null)
{
is.close();
}
if (hc != null)
{
hc.close();
}
}
return result;
Tried different codes with byte buffers, streams, etc, result is always the same. What's the problem?
try it
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
public class Transport {
public static int BUFFER_LENGTH = 100;//1024;
public static boolean USE_FLUSH = false;
static {
if (DeviceDetect.getDeivice() == DeviceDetect.SAMSUNG) {
BUFFER_LENGTH = 1024;
USE_FLUSH = true;
}
}
public static String SESSION_COOKIE = null;
private static int rnd = 1;
private static final String request(String url, String method, Hashtable params) throws IOException {
HttpConnection conn = null;
DataOutputStream dos = null;
InputStream in = null;
try {
String encodedParams = null;
if (params != null && params.size() > 0) {
encodedParams = getEncodedParams(params);
}
if (method == null) {
if (encodedParams.length() < 2000) {
method = "GET";
} else {
method = "POST";
}
}
method = method != null && method.equalsIgnoreCase("POST") ? HttpConnection.POST : HttpConnection.GET;
if (method.equalsIgnoreCase(HttpConnection.GET)) {
if (encodedParams != null) {
url += (url.indexOf("?") == -1 ? "?" : "&") + encodedParams;
encodedParams = null;
}
url += (url.indexOf("?") == -1 ? "?" : "&") + "_rnd=" + rnd++;
}
conn = (HttpConnection) Connector.open(url, Connector.READ_WRITE, true);
if (conn == null) {
throw new IOException("HttpConnection is null, please check Access Point configuration");
}
conn.setRequestMethod(method);
conn.setRequestProperty("User-Agent", UserAgent.getUserAgent());
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
if (SESSION_COOKIE != null) {
conn.setRequestProperty("Cookie", SESSION_COOKIE);
}
byte[] buff = new byte[BUFFER_LENGTH];
if (encodedParams != null) {
byte[] bytes = encodedParams.getBytes("UTF-8");
String lengthStr = bytes.length + "";
conn.setRequestProperty("Content-Length", lengthStr);
dos = conn.openDataOutputStream();
if (dos == null) {
throw new IOException("OutputStream is null, please check Access Point configuration");
}
for (int i = 0, l = bytes.length; i < l; i += Transport.BUFFER_LENGTH) {
if (Transport.BUFFER_LENGTH == 1) {
dos.writeByte(bytes[i]);
} else {
int count = Math.min(Transport.BUFFER_LENGTH, l - i);
System.arraycopy(bytes, i, buff, 0, count);
dos.write(buff, 0, count);
}
if (Transport.USE_FLUSH) {
dos.flush();
}
}
dos.flush();
try {
dos.close();
} catch (IOException ex) {
}
}
String setCookie = conn.getHeaderField("Set-Cookie");
if (setCookie != null) {
int ind1 = setCookie.indexOf("JSESSIONID=");
if (ind1 > -1) {
int ind2 = setCookie.indexOf(";", ind1);
SESSION_COOKIE = ind2 == -1 ? setCookie.substring(ind1) : setCookie.substring(ind1, ind2 + 1);
}
}
in = conn.openInputStream();
if (in == null) {
throw new IOException("InputStream is null, please check Access Point configuration");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int n = in.read(buff);
while (n > -1) {
baos.write(buff, 0, n);
n = in.read(buff);
}
baos.flush();
baos.close();
String response = new String(baos.toByteArray(), "UTF-8");
try {
in.close();
} catch (Exception ex) {
}
try {
conn.close();
} catch (Exception ex) {
}
return response;
} finally {
try {
dos.close();
} catch (Exception ex) {
}
try {
in.close();
} catch (Exception ex) {
}
try {
conn.close();
} catch (Exception ex) {
}
}
}
public static String getEncodedParams(Hashtable params) throws IOException {
String str = "";
Enumeration keys = params.keys();
while (keys.hasMoreElements()) {
String name = (String) keys.nextElement();
Object value = params.get(name);
if (value == null || name == null) {
continue;
}
str += "&" + URLEncoder.encode(name.toString(), "UTF-8") + "=" + URLEncoder.encode(value.toString(), "UTF-8");
}
if (str.length() > 1) {
str = str.substring(1);
}
return str;
}
}
I am not sure if this will work for you but I had a similar problem and found that specifying a port number made it work (on some older Nokia models). i.e convert:
http://www.mysite.com/my_page.html
to:
http://mysite.com:80/my_page.html