Working with Properties and Secondary Types

Data Types

CMIS 1.0 CMIS 1.1

The table below shows how the CMIS data types are mapped to Java and C# data types. Multi-value property values are set and returned as lists of these data types.

CMIS Data Type OpenCMIS (Java) PortCMIS (C#)
string String string
boolean Boolean bool
decimal BigDecimal, float, double, byte, short, int, long decimal, float, double
integer BigInteger, byte, short, int, long BigInteger, sbyte, byte, short, ushort, int, uint, long
datetime GregorianCalendar, Date DateTime
uri String string
id String string
html String string

Properties

Retrieving Properties

Note

Only the properties that have been requested are available. Use an Operation Context to define, which properties should be provided by the repository.

The value of a property that is not set, has not been provided by the repository, or of a property that does not exits is null.

OpenCMIS (Java)

Document doc = ...

// properties defined in the CMIS specification have getters (here are just a few examples)
String id = doc.getId();
String name = doc.getName();
String creator = doc.getCreatedBy();
GregorianCalendar lastModification = doc.getLastModificationDate();


// all property values can be accessed by their property ID
String name2 = doc.getPropertyValue("cmis:name");
BigInteger projectNumber = doc.getPropertyValue("project:number");

// multi value property values are always returned as lists
List<String> colors = doc.getPropertyValue("project:colors");

// there is detailed information about a property available for generic clients
Property<String> nameProp = doc.getProperty("cmis:name");
PropertyType namePropType = nameProp.getType();
boolean nameMultiValued = nameProp.isMultiValued();
String name3 = nameProp.getValue();

Property<Boolean> lightsProp = doc.getProperty("lights:on");
PropertyType lightsPropType = lightsProp.getType();
boolean lightsMultiValued = lightsProp.isMultiValued();
Boolean lightsValue = lightsProp.getValue();

PortCMIS (C#)

IDocument doc = ...

// properties defined in the CMIS specification have getters (here are just a few examples)
string id = doc.Id;
string name = doc.Name;
string creator = doc.CreatedBy;
DateTime? lastModification = doc.LastModificationDate;

// all property values can be accessed by their property ID
string name2 = doc.GetPropertyAsStringValue("cmis:name");
BigInteger projectNumber = (BigInteger)doc.GetPropertyValue("project:number");

// multi value property values are always returned as lists
IList<string> colors = (IList<string>)doc.GetPropertyValue("project:colors");

// there is detailed information about a property available for generic clients
IProperty nameProp = doc["cmis:name"];
PropertyType? namePropType = nameProp.PropertyType;
bool nameMultiValued = nameProp.IsMultiValued;
string name3 = (string)nameProp.Value;

IProperty lightsProp = doc["lights:on"];
PropertyType? lightsPropType = lightsProp.PropertyType;
bool lightsMultiValued = lightsProp.IsMultiValued;
bool? lightsValue = (bool?)lightsProp.Value;

Setting Properties

Before OpenCMIS or PortCMIS sends properties to a repository, it checks the type definition whether the properties exist or not, if the data types match, and if multi-value properties contain null values. If it detects a problem, it throws an exception before it sends anything to the repository.

If a property cannot be set, for example because it is a read-only property, OpenCMIS or PortCMIS silently filters out the property. The value is not sent to the repository.

OpenCMIS (Java)

Map<String, Object> properties = new HashMap<String, Object>();

// adding single value properties
properties.put(PropertyIds.NAME, "the-tower");
properties.put("project:number", 1234);
properties.put("project:now", new GregorianCalendar());
properties.put("project:onTime", true);
properties.put("project:budget", new BigDecimal("654321.98"));

// adding a multi value property
List<String> colors = new ArrayList<String>();
colors.add("red");
colors.add("green");
colors.add("blue");

properties.put("project:colors", colors); 

// unsetting a property
properties.put("project:something", null);

// call create... or update...

PortCMIS (C#)

IDictionary<string, object> properties = new Dictionary<string, object>();

// adding single value properties
properties[PropertyIds.Name] = "the-tower";
properties["project:number"] = 1234;
properties["project:now"] = DateTime.Now;
properties["project:onTime"] = true;
properties["project:budget"] = 654321.98M;

// adding a multi value property
IList<string> colors = new List<string>();
colors.Add("red");
colors.Add("green");
colors.Add("blue");

properties["project:colors"] = colors; 

// unsetting a property
properties["project:something"] = null;

// call Create... or Update...

Secondary Types

CMIS 1.1 Spec 2.1.19

Secondary types can be added during creation of an object and later added and removed by updating its properties.

In general, secondary types can be added and removed at any time. But a repository may have rules and constraints that prevents a client from making those changes.

Setting Secondary Types

OpenCMIS (Java)

Folder parent = ...

Map<String, Object> properties = new HashMap<String, Object>();

// set standard CMIS properties
properties.put(PropertyIds.NAME, "MyNewDocument");
properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");

// add two secondary types
List<String> secondaryTypes = new ArrayList<String>();
secondaryTypes.add("custom:classifictaion");
secondaryTypes.add("custom:draft");

properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes);

// set secondary type properties
properties.put("classifictaion", "confidential");
properties.put("draftState", "early");

ContentStream contentStream = ...

// create the document
Document newDoc = parent.createDocument(properties, contentStream, VersioningState.NONE);

PortCMIS (C#)

IFolder parent = ...

IDictionary<string, object> properties = new Dictionary<string, object>();

// set standard CMIS properties
properties[PropertyIds.Name] = "MyNewDocument";
properties[PropertyIds.ObjectTypeId] = "cmis:document";

// add two secondary types
IList<string> secondaryTypes = new List<string>();
secondaryTypes.Add("custom:classifictaion");
secondaryTypes.Add("custom:draft");

properties[PropertyIds.SecondaryObjectTypeIds] = secondaryTypes;

// set secondary type properties
properties["classifictaion"] = "confidential";
properties["draftState"] = "early";

ContentStream contentStream = ...

// create the document
IDocument newDoc = parent.CreateDocument(properties, contentStream, VersioningState.None);

Adding Secondary Types

OpenCMIS (Java)

CmisObject cmisObject = ...

// get current list of secondary types
List<String> secondaryTypes = doc.getPropertyValue(PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
if (secondaryTypes == null) {
    secondaryTypes = new ArrayList<String>();
}

Map<String, Object> properties = new HashMap<String, Object>();

// add the new secondary type
secondaryTypes.add("custom:classifictaion");
properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes);

// set secondary type property
properties.put("classifictaion", "public");

// update
cmisObject.updateProperties(properties);

OpenCMIS (Java)

// the convenient way...

CmisObject cmisObject = ...

// set secondary type property
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("classifictaion", "public");

// update with secondary type
cmisObject.updateProperties(properties, Collections.singletonList("custom:classifictaion"), null);

PortCMIS (C#)

ICmisObject cmisObject = ...

// get current list of secondary types
IList<string> secondaryTypes = (IList<string>)doc.GetPropertyValue(PropertyIds.SecondaryObjectTypeIds);
if (secondaryTypes == null) {
    secondaryTypes = new List<string>();
}

IDictonary<string, object> properties = new Dictonary<string, object>();

// add the new secondary type
secondaryTypes.Add("custom:classifictaion");
properties[PropertyIds.SecondaryObjectTypeIds] = secondaryTypes;

// set secondary type property
properties["classifictaion"] = "public";

// update
cmisObject.UpdateProperties(properties);

Removing Secondary Types

OpenCMIS (Java)

CmisObject cmisObject = ...

// get the current list of secondary types
List<String> secondaryTypes = doc.getPropertyValue(PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
if (secondaryTypes == null || !secondaryTypes.contains("custom:classifictaion")) {
    // there is nothing to remove
    return;
}

Map<String, Object> properties = new HashMap<String, Object>();

// remove the new secondary type
secondaryTypes.remove("custom:classifictaion");
properties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypes);

// update
cmisObject.updateProperties(properties);

OpenCMIS (Java)

// the convenient way...

CmisObject cmisObject = ...

// remove secondary type
cmisObject.updateProperties(null, null, Collections.singletonList("custom:classifictaion"));

PortCMIS (C#)

ICmisObject cmisObject = ...

// get current list of secondary types
IList<string> secondaryTypes = (IList<string>)doc.GetPropertyValue(PropertyIds.SecondaryObjectTypeIds);
if (secondaryTypes == null || !secondaryTypes.Contains("custom:classifictaion")) {
    // there is nothing to remove
    return;
}

IDictionary<string, object> properties = new Dictionary<string, object>();

// remove the secondary type
secondaryTypes.Remove("custom:classifictaion");
properties[PropertyIds.SecondaryObjectTypeIds] = secondaryTypes;

// update
cmisObject.UpdateProperties(properties);