use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class NodeDelegate method setProperty.
/**
* Set a property
*
* @return the set property
*/
@Nonnull
public PropertyDelegate setProperty(PropertyState propertyState, boolean exactTypeMatch, boolean setProtected) throws RepositoryException {
Tree tree = getTree();
String name = propertyState.getName();
Type<?> type = propertyState.getType();
PropertyState old = tree.getProperty(name);
if (old != null && old.isArray() && !propertyState.isArray()) {
throw new ValueFormatException("Can not assign a single value to multi-valued property: " + propertyState);
}
if (old != null && !old.isArray() && propertyState.isArray()) {
throw new ValueFormatException("Can not assign multiple values to single valued property: " + propertyState);
}
Tree definition = findMatchingPropertyDefinition(getNodeTypes(tree), name, type, exactTypeMatch);
if (definition == null) {
throw new ConstraintViolationException("No matching property definition: " + propertyState);
} else if (!setProtected && TreeUtil.getBoolean(definition, JCR_PROTECTED)) {
throw new ConstraintViolationException("Property is protected: " + propertyState);
}
Type<?> requiredType = Type.fromString(TreeUtil.getString(definition, JCR_REQUIREDTYPE));
if (requiredType != Type.UNDEFINED) {
if (TreeUtil.getBoolean(definition, JCR_MULTIPLE)) {
requiredType = requiredType.getArrayType();
}
ValueHelper.checkSupportedConversion(propertyState.getType().tag(), requiredType.tag());
propertyState = PropertyStates.convert(propertyState, requiredType);
}
tree.setProperty(propertyState);
return new PropertyDelegate(sessionDelegate, tree, name);
}
use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class NodeDelegate method updateMixins.
public void updateMixins(Set<String> addMixinNames, Set<String> removedOakMixinNames) throws RepositoryException {
// 1. set all new mixin types including validation
for (String oakMixinName : addMixinNames) {
addMixin(oakMixinName);
}
if (!removedOakMixinNames.isEmpty()) {
// 2. retrieve the updated set of mixin types, remove the mixins that should no longer be present
Set<String> mixinNames = newLinkedHashSet(getNames(getTree(), JCR_MIXINTYPES));
if (mixinNames.removeAll(removedOakMixinNames)) {
// FIXME: add mixins to add again as the removal may change the effect of type inheritance as evaluated during #addMixin
mixinNames.addAll(addMixinNames);
tree.setProperty(JCR_MIXINTYPES, mixinNames, NAMES);
}
// 3. deal with locked nodes
boolean wasLockable = isNodeType(MIX_LOCKABLE);
boolean isLockable = isNodeType(MIX_LOCKABLE);
if (wasLockable && !isLockable && holdsLock(false)) {
// TODO: This should probably be done in a commit hook
unlock();
sessionDelegate.refresh(true);
}
// 4. clean up set of properties and child nodes such that all child items
// have a valid item definition according to the effective node type present
// after having updated the mixin property. this includes removing all
// protected properties and child nodes associated with the removed mixin
// type(s), as there's no way for the client to do that. Other items
// defined in this mixin type might also need to be removed if there
// is no longer a matching item definition available.
Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
List<Tree> removed = new ArrayList<Tree>();
for (String name : removedOakMixinNames) {
removed.add(typeRoot.getChild(name));
}
List<Tree> remaining = getNodeTypes(tree, typeRoot);
for (PropertyState property : tree.getProperties()) {
String name = property.getName();
Type<?> type = property.getType();
Tree oldDefinition = findMatchingPropertyDefinition(removed, name, type, true);
if (oldDefinition != null) {
Tree newDefinition = findMatchingPropertyDefinition(remaining, name, type, true);
if (newDefinition == null || (getBoolean(oldDefinition, JCR_PROTECTED) && !getBoolean(newDefinition, JCR_PROTECTED))) {
tree.removeProperty(name);
}
}
}
for (Tree child : tree.getChildren()) {
String name = child.getName();
Set<String> typeNames = newLinkedHashSet();
for (Tree type : getNodeTypes(child, typeRoot)) {
typeNames.add(TreeUtil.getName(type, JCR_NODETYPENAME));
addAll(typeNames, getNames(type, REP_SUPERTYPES));
}
Tree oldDefinition = findMatchingChildNodeDefinition(removed, name, typeNames);
if (oldDefinition != null) {
Tree newDefinition = findMatchingChildNodeDefinition(remaining, name, typeNames);
if (newDefinition == null || (getBoolean(oldDefinition, JCR_PROTECTED) && !getBoolean(newDefinition, JCR_PROTECTED))) {
child.remove();
}
}
}
}
}
use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class NodeImpl method internalSetPrimaryType.
private void internalSetPrimaryType(final String nodeTypeName) throws RepositoryException {
// TODO: figure out the right place for this check
// throws on not found
NodeType nt = getNodeTypeManager().getNodeType(nodeTypeName);
if (nt.isAbstract() || nt.isMixin()) {
throw new ConstraintViolationException(getNodePath());
}
// TODO: END
PropertyState state = PropertyStates.createProperty(JCR_PRIMARYTYPE, getOakName(nodeTypeName), NAME);
dlg.setProperty(state, true, true);
dlg.setOrderableChildren(nt.hasOrderableChildNodes());
}
use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class NodeImpl method internalSetProperty.
private Property internalSetProperty(final String jcrName, final Value[] values, final int type, final boolean exactTypeMatch) throws RepositoryException {
final String oakName = getOakPathOrThrow(checkNotNull(jcrName));
final PropertyState state = createMultiState(oakName, compact(values), Type.fromTag(type, true));
if (values.length > MV_PROPERTY_WARN_THRESHOLD) {
LOG.warn("Large multi valued property [{}/{}] detected ({} values).", dlg.getPath(), jcrName, values.length);
}
return perform(new ItemWriteOperation<Property>("internalSetProperty") {
@Override
public void checkPreconditions() throws RepositoryException {
super.checkPreconditions();
if (!isCheckedOut() && getOPV(dlg.getTree(), state) != OnParentVersionAction.IGNORE) {
throw new VersionException(format("Cannot set property. Node [%s] is checked in.", getNodePath()));
}
}
@Nonnull
@Override
public Property perform() throws RepositoryException {
return new PropertyImpl(dlg.setProperty(state, exactTypeMatch, false), sessionContext);
}
@Override
public String toString() {
return format("Setting property [%s/%s]", dlg.getPath(), jcrName);
}
});
}
use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class ObservationTest method filterPropertyOfChild.
@Test
public void filterPropertyOfChild() throws RepositoryException, ExecutionException, InterruptedException {
assumeTrue(observationManager instanceof ObservationManagerImpl);
ObservationManagerImpl oManager = (ObservationManagerImpl) observationManager;
ExpectationListener listener = new ExpectationListener();
FilterBuilder builder = new FilterBuilder();
// Events for all items that have a property "b/c/foo" with value "bar"
builder.condition(builder.property(Selectors.fromThis("b/c"), "foo", new Predicate<PropertyState>() {
@Override
public boolean apply(PropertyState property) {
return "bar".equals(property.getValue(STRING));
}
}));
oManager.addEventListener(listener, builder.build());
Node testNode = getNode(TEST_PATH);
Node a = testNode.addNode("a");
a.addNode("b").addNode("c").setProperty("foo", "bar");
a.addNode("d");
Node x = testNode.addNode("x");
x.addNode("b").addNode("c").setProperty("foo", "baz");
x.addNode("d");
listener.expect(a.getPath(), NODE_ADDED);
testNode.getSession().save();
List<Expectation> missing = listener.getMissing(TIME_OUT, TimeUnit.SECONDS);
assertTrue("Missing events: " + missing, missing.isEmpty());
List<Event> unexpected = listener.getUnexpected();
assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
}
Aggregations