You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2006/07/12 15:33:27 UTC
svn commit: r421270 [11/23] - in /jackrabbit/trunk/contrib/spi: ./ commons/
commons/src/ commons/src/main/ commons/src/main/java/
commons/src/main/java/org/ commons/src/main/java/org/apache/
commons/src/main/java/org/apache/jackrabbit/ commons/src/main...
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ValueConstraint.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ValueConstraint.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ValueConstraint.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ValueConstraint.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,884 @@
+/*
+ * 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.jackrabbit.jcr2spi.nodetype;
+
+import org.apache.jackrabbit.name.IllegalNameException;
+import org.apache.jackrabbit.name.MalformedPathException;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.UnknownPrefixException;
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.name.NameFormat;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.value.DateValue;
+import org.apache.jackrabbit.value.QValue;
+import org.apache.jackrabbit.util.ISO8601;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import java.util.Calendar;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * <code>ValueConstraint</code> and its subclasses are used to check the
+ * syntax of a value constraint and to test if a specific value satisfies
+ * it.
+ */
+public abstract class ValueConstraint {
+
+ protected static Logger log = LoggerFactory.getLogger(ValueConstraint.class);
+
+ public static final ValueConstraint[] EMPTY_ARRAY = new ValueConstraint[0];
+
+ final String qualifiedDefinition;
+
+ protected ValueConstraint(String qualifiedDefinition) {
+ this.qualifiedDefinition = qualifiedDefinition;
+ }
+
+ /**
+ * For constraints that are not namespace prefix mapping sensitive this
+ * method returns the same result as <code>{@link #getQualifiedDefinition()}</code>.
+ * <p/>
+ * Those that are namespace prefix mapping sensitive (e.g.
+ * <code>NameConstraint</code>, <code>PathConstraint</code> and
+ * <code>ReferenceConstraint</code>) use the given <code>nsResolver</code>
+ * to reflect the current mapping in the returned value.
+ *
+ * @return the definition of this constraint.
+ * @see #getQualifiedDefinition()
+ */
+ public String getDefinition(NamespaceResolver nsResolver) {
+ return qualifiedDefinition;
+ }
+
+ // DIFF JACKRABBIT: added method
+ /**
+ * @return the qualified definition String
+ * @see #getDefinition(NamespaceResolver)
+ */
+ public String getQualifiedDefinition() {
+ return qualifiedDefinition;
+ }
+
+ /**
+ *
+ * @param value
+ * @throws ConstraintViolationException
+ * @throws RepositoryException
+ */
+ abstract void check(QValue value) throws ConstraintViolationException, RepositoryException;
+
+
+ //-------------------------------------------< java.lang.Object overrides >
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ } else if (other instanceof ValueConstraint) {
+ return qualifiedDefinition.equals(((ValueConstraint) other).qualifiedDefinition);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the hashCode of the definition String
+ *
+ * @return the hashCode of the definition String
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ return qualifiedDefinition.hashCode();
+ }
+
+ //--------------------------------------------------------------------------
+ // DIFF JACKRABBIT: method added
+ /**
+ * Create a new <code>ValueConstraint</code> from the String representation.
+ * Note, that the definition must be in the qualified format in case the type
+ * indicates {@link PropertyType#NAME}, {@link PropertyType#PATH} or {@link PropertyType#REFERENCE}
+ *
+ * @param type
+ * @param qualifiedDefinition
+ * @return
+ * @throws InvalidConstraintException
+ */
+ public static ValueConstraint create(int type, String qualifiedDefinition)
+ throws InvalidConstraintException {
+ if (qualifiedDefinition == null) {
+ throw new IllegalArgumentException("illegal definition (null)");
+ }
+ switch (type) {
+ // constraints which are not qName senstive
+ case PropertyType.STRING:
+ return new StringConstraint(qualifiedDefinition);
+
+ case PropertyType.BOOLEAN:
+ return new BooleanConstraint(qualifiedDefinition);
+
+ case PropertyType.BINARY:
+ return new NumericConstraint(qualifiedDefinition);
+
+ case PropertyType.DATE:
+ return new DateConstraint(qualifiedDefinition);
+
+ case PropertyType.LONG:
+ case PropertyType.DOUBLE:
+ return new NumericConstraint(qualifiedDefinition);
+
+ // qName sensitive constraints: create from qualified string
+ case PropertyType.NAME:
+ return new NameConstraint(qualifiedDefinition);
+
+ case PropertyType.PATH:
+ return new PathConstraint(qualifiedDefinition);
+
+ case PropertyType.REFERENCE:
+ return new ReferenceConstraint(qualifiedDefinition);
+
+ default:
+ throw new IllegalArgumentException("unknown/unsupported target type for constraint: "
+ + PropertyType.nameFromValue(type));
+ }
+ }
+
+ /**
+ *
+ * @param type
+ * @param definition
+ * @param nsResolver
+ * @return
+ * @throws InvalidConstraintException
+ */
+ public static ValueConstraint create(int type, String definition,
+ NamespaceResolver nsResolver)
+ throws InvalidConstraintException {
+ if (definition == null) {
+ throw new IllegalArgumentException("illegal definition (null)");
+ }
+ switch (type) {
+ case PropertyType.STRING:
+ return new StringConstraint(definition);
+
+ case PropertyType.BOOLEAN:
+ return new BooleanConstraint(definition);
+
+ case PropertyType.BINARY:
+ return new NumericConstraint(definition);
+
+ case PropertyType.DATE:
+ return new DateConstraint(definition);
+
+ case PropertyType.LONG:
+ case PropertyType.DOUBLE:
+ return new NumericConstraint(definition);
+
+ case PropertyType.NAME:
+ return new NameConstraint(definition, nsResolver);
+
+ case PropertyType.PATH:
+ return new PathConstraint(definition, nsResolver);
+
+ case PropertyType.REFERENCE:
+ return new ReferenceConstraint(definition, nsResolver);
+
+ default:
+ throw new IllegalArgumentException("unknown/unsupported target type for constraint: "
+ + PropertyType.nameFromValue(type));
+ }
+ }
+
+ // DIFF JACKRABBIT: moved from EffectiveNodeType
+ /**
+ * Tests if the value constraints defined in the property definition
+ * <code>pd</code> are satisfied by the the specified <code>values</code>.
+ * <p/>
+ * Note that the <i>protected</i> flag is not checked. Also note that no
+ * type conversions are attempted if the type of the given values does not
+ * match the required type as specified in the given definition.
+ *
+ * @param pd
+ * @param values
+ * @throws ConstraintViolationException
+ */
+ public static void checkValueConstraints(QPropertyDefinition pd, QValue[] values)
+ throws ConstraintViolationException, RepositoryException {
+ // check multi-value flag
+ if (!pd.isMultiple() && values != null && values.length > 1) {
+ throw new ConstraintViolationException("the property is not multi-valued");
+ }
+
+ String[] constraints = pd.getValueConstraints();
+ if (constraints == null || constraints.length == 0) {
+ // no constraints to check
+ return;
+ }
+ if (values != null && values.length > 0) {
+ // check value constraints on every value
+ for (int i = 0; i < values.length; i++) {
+ // constraints are OR-ed together
+ boolean satisfied = false;
+ ConstraintViolationException cve = null;
+ for (int j = 0; j < constraints.length; j++) {
+ try {
+ ValueConstraint cnstr = ValueConstraint.create(pd.getRequiredType(), constraints[j]);
+ cnstr.check(values[i]);
+ satisfied = true;
+ break;
+ } catch (ConstraintViolationException e) {
+ cve = e;
+ continue;
+ } catch (InvalidConstraintException e) {
+ cve = new ConstraintViolationException(e.getMessage(), e);
+ continue;
+ }
+ }
+ if (!satisfied) {
+ // re-throw last exception we encountered
+ throw cve;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * <code>BooleanConstraint</code> ...
+ */
+class BooleanConstraint extends ValueConstraint {
+ final boolean reqBool;
+
+ BooleanConstraint(String definition) throws InvalidConstraintException {
+ super(definition);
+
+ // constraint format: 'true' or 'false'
+ if (definition.equals("true")) {
+ reqBool = true;
+ } else if (definition.equals("false")) {
+ reqBool = false;
+ } else {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for BOOLEAN values";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ }
+
+ private void check(boolean bool) throws ConstraintViolationException {
+ if (bool != reqBool) {
+ throw new ConstraintViolationException("'" + bool + "' does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.BOOLEAN:
+ check(Boolean.valueOf(value.getString()).booleanValue());
+ return;
+
+ default:
+ String msg = "BOOLEAN constraint can not be applied to value of type: "
+ + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+/**
+ * <code>StringConstraint</code> ...
+ */
+class StringConstraint extends ValueConstraint {
+ final Pattern pattern;
+
+ StringConstraint(String definition) throws InvalidConstraintException {
+ super(definition);
+
+ // constraint format: regexp
+ try {
+ pattern = Pattern.compile(definition);
+ } catch (PatternSyntaxException pse) {
+ String msg = "'" + definition + "' is not valid regular expression syntax";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, pse);
+ }
+ }
+
+ private void check(String text) throws ConstraintViolationException {
+ if (text == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ Matcher matcher = pattern.matcher(text);
+ if (!matcher.matches()) {
+ throw new ConstraintViolationException("'" + text + "' does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.STRING:
+ check(value.toString());
+ return;
+
+ default:
+ String msg = "STRING constraint can not be applied to value of type: " + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+/**
+ * <code>NumericConstraint</code> ...
+ */
+class NumericConstraint extends ValueConstraint {
+ final boolean lowerInclusive;
+ final Double lowerLimit;
+ final boolean upperInclusive;
+ final Double upperLimit;
+
+ NumericConstraint(String definition) throws InvalidConstraintException {
+ super(definition);
+
+ // format: '(<min>, <max>)', '[<min>, <max>]', '(, <max>)' etc.
+ Pattern pattern = Pattern.compile("([\\(\\[]) *(\\-?\\d+\\.?\\d*)? *, *(\\-?\\d+\\.?\\d*)? *([\\)\\]])");
+ Matcher matcher = pattern.matcher(definition);
+ if (matcher.matches()) {
+ try {
+ // group 1 is lower inclusive/exclusive
+ String s = matcher.group(1);
+ lowerInclusive = s.equals("[");
+ // group 2 is lower limit
+ s = matcher.group(2);
+ if (s == null || s.length() == 0) {
+ lowerLimit = null;
+ } else {
+ lowerLimit = Double.valueOf(matcher.group(2));
+ }
+ // group 3 is upper limit
+ s = matcher.group(3);
+ if (s == null || s.length() == 0) {
+ upperLimit = null;
+ } else {
+ upperLimit = Double.valueOf(matcher.group(3));
+ }
+ // group 4 is lower inclusive/exclusive
+ s = matcher.group(4);
+ upperInclusive = s.equals("]");
+ if (lowerLimit == null && upperLimit == null) {
+ String msg = "'" + definition + "' is not a valid value constraint"
+ + " format for numeric types: neither lower- nor upper-limit specified";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ if (lowerLimit != null && upperLimit != null) {
+ if (lowerLimit.doubleValue() > upperLimit.doubleValue()) {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for numeric types: lower-limit exceeds upper-limit";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ }
+ } catch (NumberFormatException nfe) {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for numeric types";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, nfe);
+ }
+ } else {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for numeric values";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ }
+
+ private void check(Double number) throws ConstraintViolationException {
+ if (number == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ check(number.doubleValue());
+ }
+
+ private void check(Long number) throws ConstraintViolationException {
+ if (number == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ check(number.doubleValue());
+ }
+
+ private void check(double number) throws ConstraintViolationException {
+ if (lowerLimit != null) {
+ if (lowerInclusive) {
+ if (number < lowerLimit.doubleValue()) {
+ throw new ConstraintViolationException(number
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ } else {
+ if (number <= lowerLimit.doubleValue()) {
+ throw new ConstraintViolationException(number
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ }
+ }
+ if (upperLimit != null) {
+ if (upperInclusive) {
+ if (number > upperLimit.doubleValue()) {
+ throw new ConstraintViolationException(number
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ } else {
+ if (number >= upperLimit.doubleValue()) {
+ throw new ConstraintViolationException(number
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ }
+ }
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.LONG:
+ check(Long.parseLong(value.getString()));
+ return;
+
+ case PropertyType.DOUBLE:
+ check(Double.parseDouble(value.getString()));
+ return;
+
+ case PropertyType.BINARY:
+ long length = value.getLength();
+ if (length != -1) {
+ check(length);
+ } else {
+ log.warn("failed to determine length of binary value");
+ }
+ return;
+
+ default:
+ String msg = "numeric constraint can not be applied to value of type: "
+ + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+/**
+ * <code>DateConstraint</code> ...
+ */
+class DateConstraint extends ValueConstraint {
+ final boolean lowerInclusive;
+ final Calendar lowerLimit;
+ final boolean upperInclusive;
+ final Calendar upperLimit;
+
+ DateConstraint(String definition) throws InvalidConstraintException {
+ super(definition);
+
+ // format: '(<fromDate>, <toDate>)', '[<fromDate>, <toDate>]', '[, <toDate>]' etc.
+ Pattern pattern = Pattern.compile("([\\(\\[]) *([0-9TZ\\.\\+-:]*)? *, *([0-9TZ\\.\\+-:]*)? *([\\)\\]])");
+ Matcher matcher = pattern.matcher(definition);
+ if (matcher.matches()) {
+ try {
+ // group 1 is lower inclusive/exclusive
+ String s = matcher.group(1);
+ lowerInclusive = s.equals("[");
+ // group 2 is lower limit
+ s = matcher.group(2);
+ if (s == null || s.length() == 0) {
+ lowerLimit = null;
+ } else {
+ lowerLimit = DateValue.valueOf(matcher.group(2)).getDate();
+ }
+ // group 3 is upper limit
+ s = matcher.group(3);
+ if (s == null || s.length() == 0) {
+ upperLimit = null;
+ } else {
+ upperLimit = DateValue.valueOf(matcher.group(3)).getDate();
+ }
+ // group 4 is upepr inclusive/exclusive
+ s = matcher.group(4);
+ upperInclusive = s.equals("]");
+
+ if (lowerLimit == null && upperLimit == null) {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for dates: neither min- nor max-date specified";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ if (lowerLimit != null && upperLimit != null) {
+ if (lowerLimit.after(upperLimit)) {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for dates: min-date > max-date";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ }
+ } catch (ValueFormatException vfe) {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for dates";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, vfe);
+ } catch (RepositoryException re) {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for dates";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, re);
+ }
+ } else {
+ String msg = "'" + definition
+ + "' is not a valid value constraint format for dates";
+ log.debug(msg);
+ throw new InvalidConstraintException(msg);
+ }
+ }
+
+ private void check(Calendar cal) throws ConstraintViolationException {
+ if (cal == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ if (lowerLimit != null) {
+ if (lowerInclusive) {
+ if (cal.getTimeInMillis() < lowerLimit.getTimeInMillis()) {
+ throw new ConstraintViolationException(cal
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ } else {
+ if (cal.getTimeInMillis() <= lowerLimit.getTimeInMillis()) {
+ throw new ConstraintViolationException(cal
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ }
+ }
+ if (upperLimit != null) {
+ if (upperInclusive) {
+ if (cal.getTimeInMillis() > upperLimit.getTimeInMillis()) {
+ throw new ConstraintViolationException(cal
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ } else {
+ if (cal.getTimeInMillis() >= upperLimit.getTimeInMillis()) {
+ throw new ConstraintViolationException(cal
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ }
+ }
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.DATE:
+ check(ISO8601.parse(value.getString()));
+ return;
+
+ default:
+ String msg = "DATE constraint can not be applied to value of type: "
+ + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+/**
+ * <code>PathConstraint</code> ...
+ */
+class PathConstraint extends ValueConstraint {
+ final Path path;
+ final boolean deep;
+
+ PathConstraint(String qualifiedDefinition) {
+ super(qualifiedDefinition);
+ // constraint format: qualified absolute or relative path with optional trailing wildcard
+ deep = qualifiedDefinition.endsWith("*");
+ path = Path.valueOf(qualifiedDefinition);
+ }
+
+ PathConstraint(String definition, NamespaceResolver nsResolver)
+ throws InvalidConstraintException {
+ super(definition);
+
+ // constraint format: absolute or relative path with optional trailing wildcard
+ deep = definition.endsWith("*");
+ if (deep) {
+ // trim trailing wildcard before building path
+ definition = definition.substring(0, definition.length() - 1);
+ }
+ try {
+ path = nsResolver.getQPath(definition);
+ } catch (MalformedPathException mpe) {
+ String msg = "Invalid path expression specified as value constraint: " + definition;
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, mpe);
+ }
+ }
+
+ public String getDefinition(NamespaceResolver nsResolver) {
+ try {
+ String p = nsResolver.getJCRPath(path);
+ if (!deep) {
+ return p;
+ } else if (path.denotesRoot()) {
+ return p + "*";
+ } else {
+ return p + "/*";
+ }
+ } catch (NoPrefixDeclaredException npde) {
+ // should never get here, return raw definition as fallback
+ return qualifiedDefinition;
+ }
+ }
+
+ /**
+ * Returns the String representation of the path.
+ *
+ * @return String representation of the path.
+ */
+ public String getQualifiedDefinition() {
+ return path.toString();
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.PATH:
+ Path p = Path.valueOf(value.getString());
+ // normalize paths before comparing them
+ Path p0, p1;
+ try {
+ p0 = path.getNormalizedPath();
+ p1 = p.getNormalizedPath();
+ } catch (MalformedPathException e) {
+ throw new ConstraintViolationException("path not valid: " + e);
+ }
+ if (deep) {
+ try {
+ if (!p0.isAncestorOf(p1)) {
+ throw new ConstraintViolationException(p
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ } catch (MalformedPathException e) {
+ // can't compare relative with absolute path
+ throw new ConstraintViolationException(p
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ } else {
+ // exact match required
+ if (!p0.equals(p1)) {
+ throw new ConstraintViolationException(p
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ }
+ return;
+
+ default:
+ String msg = "PATH constraint can not be applied to value of type: "
+ + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+/**
+ * <code>NameConstraint</code> ...
+ */
+class NameConstraint extends ValueConstraint {
+ final QName name;
+
+ NameConstraint(String qualifiedDefinition) {
+ super(qualifiedDefinition);
+ // constraint format: String representation of qualified name
+ name = QName.valueOf(qualifiedDefinition);
+ }
+
+ NameConstraint(String definition, NamespaceResolver nsResolver)
+ throws InvalidConstraintException {
+ super(definition);
+ // constraint format: JCR name in prefix form
+ try {
+ NameFormat.checkFormat(definition);
+ name = nsResolver.getQName(definition);
+ } catch (IllegalNameException ine) {
+ String msg = "invalid name specified as value constraint: "
+ + definition;
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, ine);
+ } catch (NameException upe) {
+ String msg = "invalid name specified as value constraint: "
+ + definition;
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, upe);
+ }
+ }
+
+ public String getDefinition(NamespaceResolver nsResolver) {
+ try {
+ return nsResolver.getJCRName(name);
+ } catch (NoPrefixDeclaredException npde) {
+ // should never get here, return raw definition as fallback
+ return qualifiedDefinition;
+ }
+ }
+
+ /**
+ * Returns the String representation of the qualified name
+ *
+ * @return String representation of the qualified name
+ */
+ public String getQualifiedDefinition() {
+ return name.toString();
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.NAME:
+ QName n = QName.valueOf(value.getString());
+ if (!name.equals(n)) {
+ throw new ConstraintViolationException(n
+ + " does not satisfy the constraint '"
+ + qualifiedDefinition + "'");
+ }
+ return;
+
+ default:
+ String msg = "NAME constraint can not be applied to value of type: "
+ + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+/**
+ * <code>ReferenceConstraint</code> ...
+ */
+class ReferenceConstraint extends ValueConstraint {
+ final QName ntName;
+
+ ReferenceConstraint(String qualifiedDefinition) {
+ super(qualifiedDefinition);
+ // format: qualified node type name
+ ntName = QName.valueOf(qualifiedDefinition);
+ }
+
+ ReferenceConstraint(String definition, NamespaceResolver nsResolver) throws InvalidConstraintException {
+ super(definition);
+
+ // format: node type name
+ try {
+ ntName = nsResolver.getQName(definition);
+ } catch (IllegalNameException ine) {
+ String msg = "invalid node type name specified as value constraint: "
+ + definition;
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, ine);
+ } catch (UnknownPrefixException upe) {
+ String msg = "invalid node type name specified as value constraint: "
+ + definition;
+ log.debug(msg);
+ throw new InvalidConstraintException(msg, upe);
+ }
+ }
+
+ public String getDefinition(NamespaceResolver nsResolver) {
+ try {
+ return nsResolver.getJCRName(ntName);
+ } catch (NoPrefixDeclaredException npde) {
+ // should never get here, return raw definition as fallback
+ return qualifiedDefinition;
+ }
+ }
+
+ /**
+ * Returns the String representation of the qualified nodetype name.
+ *
+ * @return String representation of the qualified nodetype name.
+ */
+ public String getQualifiedDefinition() {
+ return ntName.toString();
+ }
+
+ void check(QValue value) throws ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ throw new ConstraintViolationException("null value does not satisfy the constraint '" + qualifiedDefinition + "'");
+ }
+ switch (value.getType()) {
+ case PropertyType.REFERENCE:
+ // @todo check REFERENCE value constraint (requires a session)
+ /*
+ UUID targetUUID = (UUID) value.internalValue();
+ NodeImpl targetNode = (NodeImpl) session.getNodeByUUID(targetUUID.toString());
+ if (!targetNode.isNodeType(ntName)) {
+ throw new ConstraintViolationException("the node with uuid "
+ + targetUUID + " does not satisfy the constraint '" + definition + "'");
+ }
+ */
+ log.warn("validation of REFERENCE constraint is not yet implemented");
+ return;
+
+ default:
+ String msg = "REFERENCE constraint can not be applied to value of type: "
+ + PropertyType.nameFromValue(value.getType());
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ }
+}
+
+
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ValueConstraint.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ValueConstraint.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,246 @@
+/*
+ * 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.jackrabbit.jcr2spi.observation;
+
+import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType;
+import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeConflictException;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.name.Path;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * The <code>EventFilter</code> class implements the filter logic based
+ * on the session's access rights and the specified filter rules.
+ */
+class EventFilter {
+
+ /**
+ * Logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(EventFilter.class);
+
+ static final EventFilter BLOCK_ALL = new BlockAllFilter();
+
+ /**
+ * The namespaceResolver of the session this EventFilter belongs to.
+ */
+ private final NamespaceResolver nsResolver;
+
+ /**
+ * The node type registry.
+ */
+ private final NodeTypeRegistry ntReg;
+
+ /**
+ * This <code>EventFilter</code> should only allow events with the
+ * specified types.
+ */
+ private final long eventTypes;
+
+ /**
+ * Only allow Items with the specified <code>path</code>
+ */
+ private final Path path;
+
+ /**
+ * If <code>isDeep</code> is <code>true</code> also Items under <code>absPath</code>
+ * are allowed.
+ */
+ private final boolean isDeep;
+
+ /**
+ * Only allow Nodes with the specified <code>uuids</code>.
+ */
+ private final String[] uuids;
+
+ /**
+ * Only allow Nodes with the specified node type name.
+ */
+ private final QName[] nodeTypes;
+
+ /**
+ * If <code>noLocal</code> is true this filter will block events from
+ * the session that registerd this filter.
+ */
+ private final boolean noLocal;
+
+ /**
+ * Creates a new <code>EventFilter</code> instance.
+ *
+ * @param nsResolver <code>NamespaceResolver</code> attached to the
+ * <code>Session</code> that registered the {@link
+ * javax.jcr.observation.EventListener}.
+ * @param ntReg the node type registry.
+ * @param eventTypes only allow specified {@link javax.jcr.observation.Event} types.
+ * @param path only allow {@link javax.jcr.Item} with
+ * <code>path</code>.
+ * @param isDeep if <code>true</code> also allow events for {@link
+ * Item}s below <code>absPath</code>.
+ * @param uuids only allow events for {@link javax.jcr.Node}s with
+ * specified UUIDs. If <code>null</code> is passed no
+ * restriction regarding UUIDs is applied.
+ * @param nodeTypes only allow events for specified node types named:
+ * nodeTypes. If <code>null</code> no node type
+ * restriction is applied.
+ * @param noLocal if <code>true</code> no events are allowed that were
+ * created from changes related to the <code>Session</code>
+ * that registered the {@link javax.jcr.observation.EventListener}.
+ */
+ EventFilter(NamespaceResolver nsResolver,
+ NodeTypeRegistry ntReg,
+ long eventTypes,
+ Path path,
+ boolean isDeep,
+ String[] uuids,
+ QName[] nodeTypes,
+ boolean noLocal) {
+
+ this.nsResolver = nsResolver;
+ this.ntReg = ntReg;
+ this.eventTypes = eventTypes;
+ this.path = path;
+ this.isDeep = isDeep;
+ this.uuids = uuids;
+ this.noLocal = noLocal;
+ this.nodeTypes = nodeTypes;
+ }
+
+ /**
+ * Returns the <code>NamespaceResolver</code> of the <code>Session</code>
+ * associated with this <code>EventFilter</code>.
+ *
+ * @return the <code>Session</code> associated with this
+ * <code>EventFilter</code>.
+ */
+ NamespaceResolver getNamespaceResolver() {
+ return nsResolver;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>EventFilter</code> does not allow
+ * the specified <code>Event</code>; <code>false</code> otherwise.
+ *
+ * @param event the <code>EventState</code> in question.
+ * @param isLocal <code>true</code> if <code>event</code> is local.
+ * @return <code>true</code> if this <code>EventFilter</code> blocks the
+ * <code>EventState</code>.
+ * @throws RepositoryException if an error occurs while checking.
+ */
+ boolean blocks(Event event, boolean isLocal) throws RepositoryException {
+ // first do cheap checks
+
+ if (isLocal && noLocal) {
+ return true;
+ }
+
+ // check event type
+ long type = event.getType();
+ if ((eventTypes & type) == 0) {
+ return true;
+ }
+
+ // check UUIDs
+ String uuid = event.getUUID();
+ if (uuids != null) {
+ boolean match = false;
+ for (int i = 0; i < uuids.length && !match && uuid != null; i++) {
+ match = uuids[i].equals(uuid);
+ }
+ if (!match) {
+ return true;
+ }
+ }
+
+ // check node types
+ if (nodeTypes != null) {
+ boolean match = false;
+ QName[] mixinNames = event.getMixinTypeNames();
+ QName[] typeNames = new QName[mixinNames.length + 1];
+ System.arraycopy(mixinNames, 0, typeNames, 0, mixinNames.length);
+ typeNames[typeNames.length - 1] = event.getPrimaryNodeTypeName();
+ EffectiveNodeType effectiveNt;
+ try {
+ effectiveNt = ntReg.getEffectiveNodeType(typeNames);
+ } catch (NodeTypeConflictException e) {
+ log.error("Internal error: conflicting node types", e);
+ // block this weird node
+ return true;
+ }
+ for (int i = 0; i < nodeTypes.length && !match; i++) {
+ match = effectiveNt.includesNodeType(nodeTypes[i]);
+ }
+ if (!match) {
+ return true;
+ }
+ }
+
+ // finally check path
+ // the relevant path for the path filter depends on the event type
+ // for node events, the relevant path is the one returned by
+ // Event.getPath().
+ // for property events, the relevant path is the path of the
+ // node where the property belongs to.
+ Path eventPath;
+ if (type == Event.NODE_ADDED || type == Event.NODE_REMOVED) {
+ eventPath = event.getQPath();
+ } else {
+ eventPath = event.getQPath().getAncestor(1);
+ }
+ boolean match = eventPath.equals(path);
+ if (!match && isDeep) {
+ try {
+ match = eventPath.isDescendantOf(path);
+ } catch (org.apache.jackrabbit.name.MalformedPathException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return !match;
+ }
+
+
+
+ /**
+ * This class implements an <code>EventFilter</code> that blocks
+ * all {@link Event}s.
+ */
+ private static final class BlockAllFilter extends EventFilter {
+
+ /**
+ * Creates a new <code>BlockAllFilter</code>.
+ */
+ BlockAllFilter() {
+ super(null, null, 0, null, true, null, null, true);
+ }
+
+ /**
+ * Always return <code>true</code>.
+ *
+ * @return always <code>true</code>.
+ */
+ boolean blocks(Event event, boolean isLocal) {
+ return true;
+ }
+ }
+
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,140 @@
+/*
+ * 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.jackrabbit.jcr2spi.observation;
+
+import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.PathFormat;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+
+/**
+ * Implementation of the {@link javax.jcr.observation.Event} interface.
+ */
+final class EventImpl implements Event {
+
+ /**
+ * Logger instance for this class
+ */
+ private static final Logger log = LoggerFactory.getLogger(EventImpl.class);
+
+ /**
+ * The session of the {@link javax.jcr.observation.EventListener} this
+ * event will be delivered to.
+ */
+ private final NamespaceResolver nsResolver;
+
+ /**
+ * The underlying SPI event.
+ */
+ private final org.apache.jackrabbit.spi.Event event;
+
+ /**
+ * Cached String value of this <code>Event</code> instance.
+ */
+ private String stringValue;
+
+ /**
+ * Creates a new {@link javax.jcr.observation.Event} instance based on an
+ * {@link org.apache.jackrabbit.spi.Event SPI Event}.
+ *
+ * @param nsResolver <code>NamespaceResolver</code> attached to the session
+ * of the registerd <code>EventListener</code>, where this <code>Event</code>
+ * will be delivered to.
+ * @param event the underlying SPI <code>Event</code>.
+ */
+ EventImpl(NamespaceResolver nsResolver, org.apache.jackrabbit.spi.Event event) {
+ this.nsResolver = nsResolver;
+ this.event = event;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getType() {
+ return event.getType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getPath() throws RepositoryException {
+ try {
+ return PathFormat.format(event.getQPath(), nsResolver);
+ } catch (NoPrefixDeclaredException e) {
+ String msg = "internal error: encountered unregistered namespace in path";
+ log.debug(msg);
+ throw new RepositoryException(msg, e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getUserID() {
+ return event.getUserID();
+ }
+
+ /**
+ * Returns a String representation of this <code>Event</code>.
+ *
+ * @return a String representation of this <code>Event</code>.
+ */
+ public String toString() {
+ if (stringValue == null) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Event: Path: ");
+ try {
+ sb.append(getPath());
+ } catch (RepositoryException e) {
+ log.error("Exception retrieving path: " + e);
+ sb.append("[Error retrieving path]");
+ }
+ sb.append(", ").append(valueOf(getType())).append(": ");
+ sb.append(", UserId: ").append(getUserID());
+ stringValue = sb.toString();
+ }
+ return stringValue;
+ }
+
+ //----------------------------------< internal >----------------------------
+
+ /**
+ * Returns a String representation of <code>eventType</code>.
+ *
+ * @param eventType an event type defined by {@link Event}.
+ * @return a String representation of <code>eventType</code>.
+ */
+ private static String valueOf(int eventType) {
+ if (eventType == Event.NODE_ADDED) {
+ return "NodeAdded";
+ } else if (eventType == Event.NODE_REMOVED) {
+ return "NodeRemoved";
+ } else if (eventType == Event.PROPERTY_ADDED) {
+ return "PropertyAdded";
+ } else if (eventType == Event.PROPERTY_CHANGED) {
+ return "PropertyChanged";
+ } else if (eventType == Event.PROPERTY_REMOVED) {
+ return "PropertyRemoved";
+ } else {
+ return "UnknownEventType";
+ }
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,163 @@
+/*
+ * 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.jackrabbit.jcr2spi.observation;
+
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Collection;
+
+/**
+ */
+class FilteredEventIterator implements EventIterator {
+
+ /**
+ * Logger instance for this class
+ */
+ private static final Logger log = LoggerFactory.getLogger(FilteredEventIterator.class);
+
+ /**
+ * The actual {@link org.apache.jackrabbit.spi.Event}s fired by the repository service
+ * (unfiltered).
+ */
+ private final Iterator actualEvents;
+
+ /**
+ * For filtering the {@link javax.jcr.observation.Event}s.
+ */
+ private final EventFilter filter;
+
+ /**
+ * If <code>true</code> these events are local.
+ */
+ private final boolean isLocal;
+
+ /**
+ * The next {@link javax.jcr.observation.Event} in this iterator
+ */
+ private Event next;
+
+ /**
+ * Current position
+ */
+ private long pos = 0;
+
+ /**
+ * Creates a new <code>FilteredEventIterator</code>.
+ *
+ * @param c an unmodifiable Collection of {@link org.apache.jackrabbit.spi.Event}s.
+ * @param filter only event that pass the filter will be dispatched to the
+ * event listener.
+ * @param isLocal if <code>true</code> these are local events.
+ */
+ public FilteredEventIterator(Collection c,
+ EventFilter filter,
+ boolean isLocal) {
+ actualEvents = c.iterator();
+ this.filter = filter;
+ this.isLocal = isLocal;
+ fetchNext();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ Event e = next;
+ fetchNext();
+ pos++;
+ return e;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Event nextEvent() {
+ return (Event) next();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void skip(long skipNum) {
+ while (skipNum-- > 0) {
+ next();
+ }
+ }
+
+ /**
+ * Always returns <code>-1</code>.
+ *
+ * @return <code>-1</code>.
+ */
+ public long getSize() {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getPosition() {
+ return pos;
+ }
+
+ /**
+ * This method is not supported.
+ * Always throws a <code>UnsupportedOperationException</code>.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("EventIterator.remove()");
+ }
+
+ /**
+ * Returns <tt>true</tt> if the iteration has more elements. (In other
+ * words, returns <tt>true</tt> if <tt>next</tt> would return an element
+ * rather than throwing an exception.)
+ *
+ * @return <tt>true</tt> if the iterator has more elements.
+ */
+ public boolean hasNext() {
+ return (next != null);
+ }
+
+ /**
+ * Fetches the next Event from the collection of events
+ * passed in the constructor of <code>FilteredEventIterator</code>
+ * that is allowed by the {@link EventFilter}.
+ */
+ private void fetchNext() {
+ org.apache.jackrabbit.spi.Event event;
+ next = null;
+ while (next == null && actualEvents.hasNext()) {
+ event = (org.apache.jackrabbit.spi.Event) actualEvents.next();
+ try {
+ next = filter.blocks(event, isLocal) ? null : new EventImpl(filter.getNamespaceResolver(), event);
+ } catch (RepositoryException e) {
+ log.error("Exception while applying filter.", e);
+ }
+ }
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,35 @@
+/*
+ * 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.jackrabbit.jcr2spi.observation;
+
+import org.apache.jackrabbit.spi.EventIterator;
+
+/**
+ * <code>InternalEventListener</code> is similar to {@link org.apache.jackrabbit.spi.EventListener}
+ * but adds information about the location of the events. Whether they are local
+ * or external.
+ */
+public interface InternalEventListener {
+
+ /**
+ * Gets called when an event occurs.
+ *
+ * @param events the event set received.
+ * @param isLocal <code>true</code> if these are local changes.
+ */
+ public void onEvent(EventIterator events, boolean isLocal);
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,207 @@
+/*
+ * 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.jackrabbit.jcr2spi.observation;
+
+import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.util.IteratorHelper;
+import org.apache.jackrabbit.name.MalformedPathException;
+import org.apache.jackrabbit.name.NameFormat;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.QName;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventListenerIterator;
+import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.spi.EventIterator;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * <code>ObservationManagerImpl</code>...
+ */
+public class ObservationManagerImpl implements ObservationManager, InternalEventListener {
+
+ /**
+ * The logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(ObservationManagerImpl.class);
+
+ /**
+ * The session this observation manager belongs to.
+ */
+ private final NamespaceResolver nsResolver;
+
+ /**
+ * The <code>NodeTypeRegistry</code> of the session.
+ */
+ private final NodeTypeRegistry ntRegistry;
+
+ /**
+ * Live mapping of <code>EventListener</code> to <code>EventFilter</code>.
+ */
+ private final Map subscriptions = new HashMap();
+
+ /**
+ * A read only mapping of <code>EventListener</code> to <code>EventFilter</code>.
+ */
+ private Map readOnlySubscriptions;
+
+ /**
+ * Creates a new observation manager for <code>session</code>.
+ * @param nsResolver NamespaceResolver to be used by this observation manager
+ * is based on.
+ * @param ntRegistry The <code>NodeTypeRegistry</code> of the session.
+ */
+ public ObservationManagerImpl(NamespaceResolver nsResolver, NodeTypeRegistry ntRegistry) {
+ this.nsResolver = nsResolver;
+ this.ntRegistry = ntRegistry;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public void addEventListener(EventListener listener,
+ int eventTypes,
+ String absPath,
+ boolean isDeep,
+ String[] uuid,
+ String[] nodeTypeName,
+ boolean noLocal) throws RepositoryException {
+ Path path;
+ try {
+ path = nsResolver.getQPath(absPath).getCanonicalPath();
+ } catch (MalformedPathException e) {
+ throw new RepositoryException("Malformed path: " + absPath);
+ }
+
+ // create NodeType instances from names
+ QName[] nodeTypeNames;
+ if (nodeTypeName == null) {
+ nodeTypeNames = null;
+ } else {
+ try {
+ nodeTypeNames = new QName[nodeTypeName.length];
+ for (int i = 0; i < nodeTypeName.length; i++) {
+ QName ntName = NameFormat.parse(nodeTypeName[i], nsResolver);
+ if (!ntRegistry.isRegistered(ntName)) {
+ throw new RepositoryException("unknown node type: " + nodeTypeName[i]);
+ }
+ nodeTypeNames[i] = ntName;
+ }
+ } catch (NameException e) {
+ throw new RepositoryException(e.getMessage());
+ }
+ }
+
+ synchronized (subscriptions) {
+ EventFilter filter = new EventFilter(nsResolver, ntRegistry,
+ eventTypes, path, isDeep, uuid, nodeTypeNames, noLocal);
+ subscriptions.put(listener, filter);
+ readOnlySubscriptions = null;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public void removeEventListener(EventListener listener) throws RepositoryException {
+ synchronized (subscriptions) {
+ if (subscriptions.remove(listener) != null) {
+ readOnlySubscriptions = null;
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public EventListenerIterator getRegisteredEventListeners() throws RepositoryException {
+ Map activeListeners;
+ synchronized (subscriptions) {
+ ensureReadOnlyMap();
+ activeListeners = readOnlySubscriptions;
+ }
+ return new ListenerIterator(activeListeners.keySet());
+ }
+
+ //-----------------------< InternalEventListener >--------------------------
+
+ public void onEvent(EventIterator events, boolean isLocal) {
+ List eventList = new ArrayList();
+ while (events.hasNext()) {
+ eventList.add(events.nextEvent());
+ }
+ eventList = Collections.unmodifiableList(eventList);
+
+ // get active listeners
+ Map activeListeners;
+ synchronized (subscriptions) {
+ ensureReadOnlyMap();
+ activeListeners = readOnlySubscriptions;
+ }
+ for (Iterator it = activeListeners.keySet().iterator(); it.hasNext(); ) {
+ EventListener listener = (EventListener) it.next();
+ EventFilter filter = (EventFilter) activeListeners.get(listener);
+ FilteredEventIterator eventIter = new FilteredEventIterator(eventList, filter, isLocal);
+ if (eventIter.hasNext()) {
+ try {
+ listener.onEvent(eventIter);
+ } catch (Throwable t) {
+ log.warn("EventConsumer threw exception: " + t.toString());
+ log.debug("Stacktrace: ", t);
+ // move on to the next listener
+ }
+ }
+ }
+ }
+
+ //-------------------------< internal >-------------------------------------
+
+ /**
+ * Ensures that {@link #readOnlySubscriptions} is set. Callers of this
+ * method must own {@link #subscriptions} as a monitor to avoid concurrent
+ * access to {@link #subscriptions}.
+ */
+ private void ensureReadOnlyMap() {
+ if (readOnlySubscriptions == null) {
+ readOnlySubscriptions = new HashMap(subscriptions);
+ }
+ }
+
+ private static final class ListenerIterator extends IteratorHelper
+ implements EventListenerIterator {
+
+ public ListenerIterator(Collection c) {
+ super(c);
+ }
+
+ public EventListener nextEventListener() {
+ return (EventListener) next();
+ }
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,91 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
+import org.apache.jackrabbit.jcr2spi.ManagerProvider;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.spi.NodeId;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>AbstractCopy</code>...
+ */
+public abstract class AbstractCopy extends AbstractOperation {
+
+ private static Logger log = LoggerFactory.getLogger(AbstractCopy.class);
+
+ private final NodeId srcId;
+ private final NodeId destParentId;
+ private final QName destName;
+
+ private final String srcWorkspaceName;
+
+ /**
+ *
+ * @param srcPath
+ * @param destPath
+ * @param srcMgrProvider
+ */
+ AbstractCopy(Path srcPath, Path destPath, String srcWorkspaceName,
+ ManagerProvider srcMgrProvider, ItemStateValidator validator)
+ throws RepositoryException {
+
+ ItemId srcItemId = srcMgrProvider.getHierarchyManager().getItemId(srcPath);
+ if (!srcItemId.denotesNode()) {
+ throw new PathNotFoundException("Source path " + validator.safeGetJCRPath(srcItemId) + " is not a valid path.");
+ }
+ this.srcId = (NodeId)srcItemId;
+ this.destParentId = validator.getNodeId(destPath.getAncestor(1));
+ addAffectedItemId(destParentId);
+
+ // check for illegal index present in destination path
+ Path.PathElement destElement = destPath.getNameElement();
+ int index = destElement.getIndex();
+ if (index > Path.INDEX_UNDEFINED) {
+ // subscript in name element
+ String msg = "invalid destination path (subscript in name element is not allowed)";
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ this.destName = destElement.getName();
+ this.srcWorkspaceName = srcWorkspaceName;
+ }
+
+ //----------------------------------------< Access Operation Parameters >---
+ public String getWorkspaceName() {
+ return srcWorkspaceName;
+ }
+
+ public NodeId getNodeId() {
+ return srcId;
+ }
+
+ public NodeId getDestinationParentId() {
+ return destParentId;
+ }
+
+ public QName getDestinationName() {
+ return destName;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractCopy.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,60 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+import org.apache.jackrabbit.spi.ItemId;
+
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * <code>AbstractOperation</code>...
+ */
+public abstract class AbstractOperation implements Operation {
+
+ /**
+ * The collection of affected ItemIds.
+ */
+ private final Collection affectedIds = new ArrayList();
+
+ /**
+ * Returns the name of the class
+ *
+ * @return the class name
+ * @see #getClass()
+ */
+ public String getName() {
+ return getClass().getName();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public Collection getAffectedItemIds() {
+ return Collections.unmodifiableCollection(affectedIds);
+ }
+
+ /**
+ * Adds an affected <code>ItemId</code>.
+ *
+ * @param affectedId the <code>ItemId</code>s of the affected item.
+ */
+ protected void addAffectedItemId(ItemId affectedId) {
+ affectedIds.add(affectedId);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AbstractOperation.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,95 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.name.QName;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.VersionException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+/**
+ * <code>AddLabel</code>...
+ */
+public class AddLabel extends AbstractOperation {
+
+ private static Logger log = LoggerFactory.getLogger(AddLabel.class);
+
+ private final NodeId versionHistoryId;
+ private final NodeId versionId;
+ private final QName label;
+ private final boolean moveLabel;
+
+ private AddLabel(NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) {
+ this.versionHistoryId = versionHistoryId;
+ this.versionId = versionId;
+ this.label = label;
+ this.moveLabel = moveLabel;
+ }
+ //----------------------------------------------------------< Operation >---
+ /**
+ *
+ * @param visitor
+ * @throws RepositoryException
+ * @throws ConstraintViolationException
+ * @throws AccessDeniedException
+ * @throws ItemExistsException
+ * @throws NoSuchNodeTypeException
+ * @throws UnsupportedRepositoryOperationException
+ * @throws VersionException
+ */
+ public void accept(OperationVisitor visitor) throws RepositoryException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException {
+ visitor.visit(this);
+ }
+
+ //----------------------------------------< Access Operation Parameters >---
+ public NodeId getVersionHistoryId() {
+ return versionHistoryId;
+ }
+
+ public NodeId getVersionId() {
+ return versionId;
+ }
+
+ public QName getLabel() {
+ return label;
+ }
+
+ public boolean moveLabel() {
+ return moveLabel;
+ }
+
+ //------------------------------------------------------------< Factory >---
+ /**
+ *
+ * @param versionHistoryId
+ * @param versionId
+ * @param label
+ * @param moveLabel
+ * @return
+ */
+ public static Operation create(NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) {
+ return new AddLabel(versionHistoryId, versionId, label, moveLabel);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddLabel.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,97 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.name.QName;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.VersionException;
+import javax.jcr.lock.LockException;
+import java.util.List;
+
+/**
+ * <code>AddNode</code>...
+ */
+public class AddNode extends AbstractOperation {
+
+ private static Logger log = LoggerFactory.getLogger(AddNode.class);
+
+ private final NodeId parentId;
+ private final QName nodeName;
+ private final QName nodeTypeName;
+ private final NodeId id;
+
+ private AddNode(NodeId parentId, QName nodeName, QName nodeTypeName, NodeId id) {
+ this.parentId = parentId;
+ this.nodeName = nodeName;
+ this.nodeTypeName = nodeTypeName;
+ this.id = id;
+ addAffectedItemId(parentId);
+ addAffectedItemId(id);
+ }
+
+ //----------------------------------------------------------< Operation >---
+ /**
+ *
+ * @param visitor
+ */
+ public void accept(OperationVisitor visitor) throws LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ visitor.visit(this);
+ }
+
+ //----------------------------------------< Access Operation Parameters >---
+ public NodeId getParentId() {
+ return parentId;
+ }
+
+ public QName getNodeName() {
+ return nodeName;
+ }
+
+ public QName getNodeTypeName() {
+ return nodeTypeName;
+ }
+
+ public String getUuid() {
+ return (id != null) ? id.getUUID() : null;
+ }
+
+ //------------------------------------------------------------< Factory >---
+
+ public static Operation create(NodeState parentState, QName nodeName,
+ QName nodeTypeName, NodeId id) {
+ AddNode an = new AddNode(parentState.getNodeId(), nodeName, nodeTypeName, id);
+ return an;
+ }
+
+ public static NodeId getLastCreated(NodeState parentState, QName nodeName) {
+ // TODO: check if this really retrieves the child state that was created before
+ // problem: we don't know the id of the nodestate in advance -> retrieval of new state not possible.
+ List cne = parentState.getChildNodeEntries(nodeName);
+ NodeId childId = ((NodeState.ChildNodeEntry)cne.get(cne.size()-1)).getId();
+ return childId;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,92 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.value.QValue;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.VersionException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+
+/**
+ * <code>AddProperty</code>...
+ */
+public class AddProperty extends AbstractOperation {
+
+ private final NodeId parentId;
+ private final QName propertyName;
+ private final int propertyType;
+ private final QValue[] values;
+
+ private final QPropertyDefinition definition;
+
+ private AddProperty(PropertyId newPropertyId, int propertyType, QValue[] values, QPropertyDefinition definition) {
+ this.parentId = newPropertyId.getParentId();
+ this.propertyName = newPropertyId.getQName();
+ this.propertyType = propertyType;
+ this.values = values;
+ this.definition = definition;
+ addAffectedItemId(parentId);
+ addAffectedItemId(newPropertyId);
+ }
+
+ //----------------------------------------------------------< Operation >---
+ /**
+ *
+ * @param visitor
+ */
+ public void accept(OperationVisitor visitor) throws ValueFormatException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ visitor.visit(this);
+ }
+
+ //----------------------------------------< Access Operation Parameters >---
+ public NodeId getParentId() {
+ return parentId;
+ }
+
+ public QName getPropertyName() {
+ return propertyName;
+ }
+
+ public int getPropertyType() {
+ return propertyType;
+ }
+
+ public QValue[] getValues() {
+ return values;
+ }
+
+ public boolean isMultiValued() {
+ return definition.isMultiple();
+ }
+
+ //------------------------------------------------------------< Factory >---
+ public static Operation create(PropertyId newPropertyId, int propertyType,
+ QPropertyDefinition def, QValue[] values) {
+ AddProperty ap = new AddProperty(newPropertyId, propertyType, values, def);
+ return ap;
+ }
+}
\ No newline at end of file