summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2014-05-06 10:48:58 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2014-05-06 10:48:58 +0200
commitab9ee87347c3efeb98cfb2b46549272a070f04d3 (patch)
treeb48eb56150354217edc37dcee68297fffc3e1fe4
parent17087c460472faeed2dc6679e186eee847b845a7 (diff)
profile: <parameter sharedfield>
Traditionally, the value of a property and its parameter values get stored in fields reserved for that property such that there is no overlap with other properties. In such a scenario it is enough to check for unused fields used for the property value, because the corresponding parameter fields are guaranteed to be available once a repetition is found. However, once the same field is used for different properties the check and creation becomes more complicated: when parsing properties, the shared field must also be checked. It is not enough for it to be empty, it also must not be in use at all, because otherwise a value might get added to the repetition used already by some other property. This check only makes sense (and only works) for array fields. It is disabled by default and needs to be enabled explicitly with the new parameter attribute "sharedfield". Storing values must ensure that the shared array field gets resized if the parameter was not set, otherwise the check would fail to detect used repetitions. The effect of using a shared field is that arrays contain a lot of unassigned values because index overlaps between otherwise unrelated properties get avoided. This feature was needed for converting between a profile with custom labels in a X-ABLabel property attached to various contact properties (ADR, TEL, X-ABDate, etc.) via group tags and a profile using a property parameter instead. The label array field is the shared field in this case.
-rw-r--r--src/sysync/mimedirprofile.cpp57
-rwxr-xr-xsrc/sysync/mimedirprofile.h7
2 files changed, 58 insertions, 6 deletions
diff --git a/src/sysync/mimedirprofile.cpp b/src/sysync/mimedirprofile.cpp
index 5b0ecc7..a1f88b8 100644
--- a/src/sysync/mimedirprofile.cpp
+++ b/src/sysync/mimedirprofile.cpp
@@ -504,7 +504,9 @@ bool TMIMEProfileConfig::localStartElement(const char *aElementName, const char
bool defparam=false;
bool shownonempty=false; // don't show properties that have only param values, but no main value
bool showinctcap=false; // don't show parameter in CTCap by default
+ bool sharedfield=false; // assume traditional, unshared field for parameter
if (
+ !getAttrBool(aAttributes,"sharedfield",sharedfield,true) ||
!getAttrBool(aAttributes,"positional",positional,true) ||
!getAttrBool(aAttributes,"default",defparam,true) ||
!getAttrBool(aAttributes,"shownonempty",shownonempty,true) ||
@@ -513,7 +515,7 @@ bool TMIMEProfileConfig::localStartElement(const char *aElementName, const char
)
return fail("bad boolean value");
// - add parameter
- fOpenParameter = fOpenProperty->addParam(nam,defparam,positional,shownonempty,showinctcap,modeDep);
+ fOpenParameter = fOpenProperty->addParam(nam,defparam,positional,shownonempty,showinctcap,modeDep,sharedfield);
#ifndef NO_REMOTE_RULES
const char *depRuleName = getAttr(aAttributes,"rule");
TCFG_ASSIGN(fOpenParameter->dependencyRuleName,depRuleName); // save name for later resolving
@@ -936,13 +938,14 @@ void TConversionDef::addEnumNameExt(TPropertyDefinition *aProp, const char *aEnu
TParameterDefinition::TParameterDefinition(
const char *aName, bool aDefault, bool aExtendsName, bool aShowNonEmpty, bool aShowInCTCap, TMimeDirMode aModeDep
-) {
+, bool aSharedField) {
next=NULL;
TCFG_ASSIGN(paramname,aName);
defaultparam=aDefault;
extendsname=aExtendsName;
shownonempty=aShowNonEmpty;
showInCTCap=aShowInCTCap;
+ sharedField=aSharedField;
modeDependency=aModeDep;
#ifndef NO_REMOTE_RULES
ruleDependency=NULL;
@@ -1087,11 +1090,11 @@ void TPropertyDefinition::addNameExt(TProfileDefinition *aRootProfile, // for pr
TParameterDefinition *TPropertyDefinition::addParam(
const char *aName, bool aDefault, bool aExtendsName, bool aShowNonEmpty, bool aShowInCTCap, TMimeDirMode aModeDep
-)
+, bool aSharedField)
{
TParameterDefinition **paramPP = &parameterDefs;
while(*paramPP!=NULL) paramPP=&((*paramPP)->next); // find last in chain
- *paramPP = new TParameterDefinition(aName,aDefault,aExtendsName,aShowNonEmpty,aShowInCTCap, aModeDep);
+ *paramPP = new TParameterDefinition(aName,aDefault,aExtendsName,aShowNonEmpty,aShowInCTCap, aModeDep, aSharedField);
return *paramPP;
} // TPropertyDefinition::addParam
@@ -4154,6 +4157,37 @@ bool TMimeDirProfileHandler::parseProperty(
else
dostore = true; // at least one field exists, we might store
}
+ // - check if shared fields used for parameters are available;
+ // must be enabled explicitly with <parameter ... sharedfield="yes">
+ const TParameterDefinition *paramP = aPropP->parameterDefs;
+ while (paramP) {
+ if (paramP->sharedField &&
+ mimeModeMatch(paramP->modeDependency)
+#ifndef NO_REMOTE_RULES
+ && (!paramP->ruleDependency || isActiveRule(paramP->ruleDependency))
+#endif
+ ) {
+ if (paramP->convdef.fieldid==FID_NOT_SUPPORTED)
+ continue; // no field, no need to check it
+ sInt16 e_fid = paramP->convdef.fieldid /* +baseoffset */;
+ sInt16 e_rep = repoffset;
+ aItem.adjustFidAndIndex(e_fid,e_rep);
+ // - get base field
+ TItemField *e_basefldP = aItem.getField(e_fid);
+ TItemField *e_fldP = NULL;
+ if (e_basefldP)
+ e_fldP=e_basefldP->getArrayField(e_rep,true); // get leaf field, if it exists
+ if (!e_basefldP || e_fldP) {
+ // base field or leaf field is already in use
+ // (unassigned is not good enough, otherwise we might end up adding information
+ // to some other, previously parsed property using the same array field)
+ // -> skip that repetition
+ dostore=false;
+ break;
+ }
+ }
+ paramP=paramP->next;
+ }
// check if we can test more repetitions
if (!dostore) {
if (aRepArray[repid]+1<maxrep || maxrep==REP_ARRAY) {
@@ -4290,6 +4324,21 @@ bool TMimeDirProfileHandler::parseProperty(
aItem.getArrayFieldAdjusted(fid+baseoffset,repoffset,false);
}
}
+ const TParameterDefinition *paramP = aPropP->parameterDefs;
+ while (paramP) {
+ if (paramP->sharedField &&
+ mimeModeMatch(paramP->modeDependency)
+#ifndef NO_REMOTE_RULES
+ && (!paramP->ruleDependency || isActiveRule(paramP->ruleDependency))
+#endif
+ ) {
+ sInt16 fid=paramP->convdef.fieldid;
+ if (fid>=0) {
+ aItem.getArrayFieldAdjusted(fid+baseoffset,repoffset,false);
+ }
+ }
+ paramP=paramP->next;
+ }
}
if (!valuelist && repid>=0 && (notempty || !overwriteempty) && !repoffsByGroup) {
// we have used this repetition and actually stored values, so count it now
diff --git a/src/sysync/mimedirprofile.h b/src/sysync/mimedirprofile.h
index f8453b5..b4b381f 100755
--- a/src/sysync/mimedirprofile.h
+++ b/src/sysync/mimedirprofile.h
@@ -157,7 +157,7 @@ public:
class TParameterDefinition : noncopyable {
public:
// constructor/destructor
- TParameterDefinition(const char *aName, bool aDefault, bool aExtendsName, bool aShowNonEmpty, bool aShowInCTCap, TMimeDirMode aModeDep);
+ TParameterDefinition(const char *aName, bool aDefault, bool aExtendsName, bool aShowNonEmpty, bool aShowInCTCap, TMimeDirMode aModeDep, bool aSharedField);
~TParameterDefinition();
// tools
TConversionDef *setConvDef(sInt16 aFieldId=FID_NOT_SUPPORTED,sInt16 aConvMode=0,char aCombSep=0)
@@ -177,6 +177,9 @@ public:
bool shownonempty;
// flag if parameter should be (not necessarily IS, depending on SyncML version) shown in CTCap
bool showInCTCap;
+ // flag if parameter field is shared between different properties and thus needs to be checked
+ // when looking for the offset where repeating properties get stored
+ bool sharedField;
// conversion information
TConversionDef convdef;
#ifndef NO_REMOTE_RULES
@@ -244,7 +247,7 @@ public:
TPropertyDefinition(const char* aName, sInt16 aNumVals, bool aMandatory, bool aShowInCTCap, bool aSuppressEmpty, uInt16 aDelayedProcessing, char aValuesep, char aAltValuesep, uInt16 aPropertyGroupID, bool aCanFilter, TMimeDirMode aModeDep, sInt16 aGroupFieldID, bool aAllowFoldAtSep);
~TPropertyDefinition();
// tools
- TParameterDefinition *addParam(const char *aName, bool aDefault, bool aExtendsName, bool aShowNonEmpty=false, bool aShowInCTCap=false, TMimeDirMode aModeDep=numMimeModes);
+ TParameterDefinition *addParam(const char *aName, bool aDefault, bool aExtendsName, bool aShowNonEmpty=false, bool aShowInCTCap=false, TMimeDirMode aModeDep=numMimeModes, bool aSharedField=false);
void addNameExt(TProfileDefinition *aRootProfile, // for profile-global RepID generation
TNameExtIDMap aMusthave_ids, TNameExtIDMap aForbidden_ids, TNameExtIDMap aAddtlSend_ids,
sInt16 aFieldidoffs, sInt16 aMaxRepeat=1, sInt16 aRepeatInc=1, sInt16 aMinShow=-1,