stefan      2003/06/06 10:28:24

  Modified:    proposals/jcrri/src/org/apache/slide/jcr/core
                        ContentNode.java EffectiveObjectClass.java
                        ElementImpl.java ElementListener.java
                        ElementManager.java ElementManagerSupport.java
                        HierarchyNode.java IteratorHelper.java
                        NodeImpl.java PropertyImpl.java
                        RepositoryFactory.java RepositoryImpl.java
                        RootContentNode.java TicketImpl.java
  Added:       proposals/jcrri/src/org/apache/slide/jcr/core
                        ObjectClassDefImpl.java ObjectClassImpl.java
                        ObjectClassManagerImpl.java
  Removed:     proposals/jcrri/src/org/apache/slide/jcr/core
                        AutoCreatedNode.java ObjectClassManagerEx.java
  Log:
  jcr ri: objectclasses (work in progress)
  
  Revision  Changes    Path
  1.5       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ContentNode.java
  
  Index: ContentNode.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ContentNode.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  
  
  
  1.2       +361 -24   
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/EffectiveObjectClass.java
  
  Index: EffectiveObjectClass.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/EffectiveObjectClass.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- EffectiveObjectClass.java 30 May 2003 13:22:36 -0000      1.1
  +++ EffectiveObjectClass.java 6 Jun 2003 17:28:23 -0000       1.2
  @@ -64,58 +64,395 @@
   
   import org.apache.log4j.Logger;
   
  -import javax.jcr.objectclass.ObjectClass;
   import javax.jcr.ConstraintViolationException;
  +import javax.jcr.RepositoryException;
  +import javax.jcr.Value;
  +import javax.jcr.objectclass.*;
   import java.util.ArrayList;
  +import java.util.HashMap;
  +import java.util.Iterator;
  +import java.util.TreeSet;
   
   /**
    * An <code>EffectiveObjectClass</code> represents one or more
    * <code>ObjectClass</code>es as one 'effective' object class where aggregation
    * and inheritance is resolved.
  + * <p>
  + * Instances of <code>EffectiveObjectClass</code> are immutable.
    *
    * @version $Revision$, $Date$
    * @author Stefan Guggisberg
    * @since
    */
  -class EffectiveObjectClass {
  +class EffectiveObjectClass implements Cloneable {
       private static Logger log = Logger.getLogger(EffectiveObjectClass.class);
   
  +    private final ObjectClassManagerImpl ocMgr;
  +
       // list of exlicitly aggregated {i.e. merged) objectclasses
  -    private final ArrayList mergedOCs;
  +    private final TreeSet mergedOCs;
       // list of all either explicitly (through aggregation) or implicitly
       // (through inheritance) included object classes.
  -    private final ArrayList allOCs;
  +    private final TreeSet allOCs;
  +    // map of element definitions
  +    private final HashMap elemDefs;
   
       /**
  -     * Default Constructor.
  +     * Constructor.
        */
  -    EffectiveObjectClass() {
  -        mergedOCs = new ArrayList();
  -        allOCs = new ArrayList();
  +    private EffectiveObjectClass(ObjectClassManagerImpl ocMgr) {
  +        this.ocMgr = ocMgr;
  +        mergedOCs = new TreeSet();
  +        allOCs = new TreeSet();
  +        elemDefs = new HashMap();
  +    }
  +
  +    static EffectiveObjectClass create(ObjectClassManagerImpl ocMgr, String ocName)
  +            throws ConstraintViolationException, NoSuchObjectClassException, 
RepositoryException {
  +        EffectiveObjectClass eoc = new EffectiveObjectClass(ocMgr);
  +        eoc.internalMerge(ocName);
  +        return eoc;
  +    }
  +
  +    static EffectiveObjectClass create(ObjectClassManagerImpl ocMgr) {
  +        return new EffectiveObjectClass(ocMgr);
       }
   
       String[] getMergedObjectClasses() {
           return (String[]) mergedOCs.toArray(new String[mergedOCs.size()]);
       }
   
  -    AutoCreatedNode[] getAutoCreatedNodes() {
  -        return null;
  +    String[] getAllObjectClasses() {
  +        return (String[]) allOCs.toArray(new String[allOCs.size()]);
  +    }
  +
  +    ElemDef[] getElemDefs() {
  +        return (ElemDef[]) elemDefs.entrySet().toArray(new 
ElemDef[elemDefs.size()]);
  +    }
  +
  +    boolean hasElemDef(String name) {
  +        return elemDefs.containsKey(name);
  +    }
  +
  +    ElemDef getElemDef(String name) {
  +        return (ElemDef) elemDefs.get(name);
  +    }
  +
  +    NodeDef[] getNodeDefs() {
  +        ArrayList defs = new ArrayList(elemDefs.size());
  +        Iterator iter = elemDefs.entrySet().iterator();
  +        while (iter.hasNext()) {
  +            ElemDef def = (ElemDef) iter.next();
  +            if (def.isNode()) {
  +                defs.add(def);
  +            }
  +        }
  +        return (NodeDef[]) defs.toArray(new NodeDef[defs.size()]);
  +    }
  +
  +    PropDef[] getPropDefs() {
  +        ArrayList defs = new ArrayList(elemDefs.size());
  +        Iterator iter = elemDefs.entrySet().iterator();
  +        while (iter.hasNext()) {
  +            ElemDef def = (ElemDef) iter.next();
  +            if (!def.isNode()) {
  +                defs.add(def);
  +            }
  +        }
  +        return (PropDef[]) defs.toArray(new PropDef[defs.size()]);
  +    }
  +
  +    boolean containsObjectClass(String ocName) {
  +        return allOCs.contains(ocName);
  +    }
  +
  +    EffectiveObjectClass merge(String ocName) throws ConstraintViolationException, 
NoSuchObjectClassException, RepositoryException {
  +        // create a clone of this instance and perform the merge on
  +        // the 'clone' to avoid a potentially inconsistant state
  +        // of this instance if an exception is thrown during
  +        // the merge.
  +        EffectiveObjectClass copy;
  +        try {
  +            copy = (EffectiveObjectClass) clone();
  +        } catch (CloneNotSupportedException e) {
  +            // should never get here
  +            log.error("internal error", e);
  +            throw new InternalError(e.getMessage());
  +        }
  +        copy.internalMerge(ocName);
  +        return copy;
  +    }
  +
  +    EffectiveObjectClass merge(EffectiveObjectClass other) throws 
ConstraintViolationException, NoSuchObjectClassException, RepositoryException {
  +        // create a clone of this instance and perform the merge on
  +        // the 'clone' to avoid a potentially inconsistant state
  +        // of this instance if an exception is thrown during
  +        // the merge.
  +        EffectiveObjectClass copy;
  +        try {
  +            copy = (EffectiveObjectClass) clone();
  +        } catch (CloneNotSupportedException e) {
  +            // should never get here
  +            log.error("internal error", e);
  +            throw new InternalError(e.getMessage());
  +        }
  +        copy.internalMerge(other);
  +        return copy;
  +    }
  +
  +    /**
  +     * Internal helper method which merges another objectclass with <i>this</i>
  +     * instance.
  +     * <p>
  +     * Warning: This instance might be in an inconstistent state if an exception
  +     * is thrown.
  +     * @param ocName
  +     * @throws ConstraintViolationException
  +     * @throws NoSuchObjectClassException
  +     * @throws RepositoryException
  +     */
  +    synchronized private void internalMerge(String ocName) throws 
ConstraintViolationException, NoSuchObjectClassException, RepositoryException {
  +        if (containsObjectClass(ocName)) {
  +            // ignore
  +            log.warn("object class '" + ocName + "' is already contained.");
  +            return;
  +        }
  +
  +        ObjectClassDef ocd = null;
  +        try {
  +            ocd = ocMgr.getObjectClass(ocName).getDefinition();
  +        } catch (UnregisteredObjectClassException e) {
  +            // should never get here...
  +            log.warn("inconsistent state: objectclass '" + ocName + "' exists, but 
is not registered.");
  +            throw new NoSuchObjectClassException(ocName);
  +        }
  +
  +        PropertyDef[] pda = ocd.getPropertyDefs();
  +        for (int i = 0; i < pda.length; i++) {
  +            PropertyDef pd = pda[i];
  +            String name = pd.getName();
  +            if (name == null) {
  +                // @todo handle residual porperty sets (name == null)
  +            }
  +            ElemDef existing = getElemDef(name);
  +            if (existing != null) {
  +                // conflict
  +                String reason = "The property definition for '" + name + "' in 
object-class '" + ocName + "' conflicts with object-class '" + 
existing.getDefiningObjectClass() + "': name collision";
  +                log.error(reason);
  +                throw new ConstraintViolationException(reason);
  +            }
  +            // @todo implement further validations
  +
  +            // @todo handle residual porperty sets (name == null)
  +            elemDefs.put(name, new PropDef(pd, ocName));
  +        }
  +
  +        ChildNodeDef[] nda = ocd.getChildNodeDefs();
  +        for (int i = 0; i < nda.length; i++) {
  +            ChildNodeDef nd = nda[i];
  +            String name = nd.getName();
  +            if (name == null) {
  +                // @todo handle residual node sets (name == null)
  +            }
  +            ElemDef existing = getElemDef(nd.getName());
  +            if (existing != null) {
  +                // conflict
  +                String reason = "The child-node definition for '" + nd.getName() + 
"' in object-class '" + ocName + "' conflicts with object-class '" + 
existing.getDefiningObjectClass() + "': name collision";
  +                log.error(reason);
  +                throw new ConstraintViolationException(reason);
  +            }
  +            // @todo implement further validations
  +
  +            // @todo handle residual node sets (name == null)
  +            elemDefs.put(nd.getName(), new NodeDef(nd, ocName));
  +        }
  +
  +        String[] superClasses = ocd.getSuperclasses();
  +        for (int i = 0; i < superClasses.length; i++) {
  +            internalMerge(superClasses[i]);
  +        }
  +        mergedOCs.add(ocName);
  +        allOCs.add(ocName);
  +    }
  +
  +    /**
  +     * Internal helper method which merges another <code>EffectiveObjectClass</code>
  +     * instance with <i>this</i> instance.
  +     * <p>
  +     * Warning: This instance might be in an inconstistent state if an exception
  +     * is thrown.
  +     * @param other
  +     * @throws ConstraintViolationException
  +     * @throws RepositoryException
  +     */
  +    synchronized private void internalMerge(EffectiveObjectClass other) throws 
ConstraintViolationException, RepositoryException {
  +        String[] oca = other.getAllObjectClasses();
  +        boolean foundOverlap = false;
  +        for (int i = 0; i < oca.length; i++) {
  +            if (containsObjectClass(oca[i])) {
  +                // ignore
  +                log.warn("object class '" + oca[i] + "' is already contained.");
  +                foundOverlap = true;
  +            }
  +        }
  +        if (foundOverlap && (oca.length == allOCs.size())) {
  +            // ignore
  +            return;
  +        }
  +
  +        PropDef[] pda = other.getPropDefs();
  +        for (int i = 0; i < pda.length; i++) {
  +            PropDef pd = pda[i];
  +            String name = pd.getName();
  +            if (name == null) {
  +                // @todo handle residual porperty sets (name == null)
  +            }
  +            ElemDef existing = getElemDef(name);
  +            if (existing != null) {
  +                // conflict
  +                String reason = "The property definition for '" + name + "' in 
object-class '" + pd.getDefiningObjectClass() + "' conflicts with object-class '" + 
existing.getDefiningObjectClass() + "': name collision";
  +                log.error(reason);
  +                throw new ConstraintViolationException(reason);
  +            }
  +            // @todo implement further validations
  +
  +            // @todo handle residual porperty sets (name == null)
  +            elemDefs.put(name, pd);
  +        }
  +
  +        NodeDef[] nda = other.getNodeDefs();
  +        for (int i = 0; i < nda.length; i++) {
  +            NodeDef nd = nda[i];
  +            String name = nd.getName();
  +            if (name == null) {
  +                // @todo handle residual node sets (name == null)
  +            }
  +            ElemDef existing = getElemDef(name);
  +            if (existing != null) {
  +                // conflict
  +                String reason = "The child-node definition for '" + name + "' in 
object-class '" + nd.getDefiningObjectClass() + "' conflicts with object-class '" + 
existing.getDefiningObjectClass() + "': name collision";
  +                log.error(reason);
  +                throw new ConstraintViolationException(reason);
  +            }
  +            // @todo implement further validations
  +
  +            // @todo handle residual node sets (name == null)
  +            elemDefs.put(name, nd);
  +        }
  +
  +        for (int i = 0; i < oca.length; i++) {
  +            allOCs.add(oca[i]);
  +        }
  +        oca = other.getMergedObjectClasses();
  +        for (int i = 0; i < oca.length; i++) {
  +            mergedOCs.add(oca[i]);
  +        }
       }
  -/*
  -    AutoCreatedProperty[] getAutoCreatedProperties() {
  -        return null;
  +
  +    protected Object clone() throws CloneNotSupportedException {
  +        return super.clone();
       }
  -*/
  -    void merge(ObjectClass oc) throws ConstraintViolationException {
   
  +    //--------------------------------------------------------< inner classes >
  +    abstract class ElemDef {
  +        protected final String name;
  +        protected final String definingObjectClass;
  +        protected final boolean autoCreate;
  +        protected final int onVersion;
  +        protected final boolean readOnly;
  +
  +        protected final boolean node;
  +
  +        ElemDef(ChildNodeDef def, String definingObjectClass) {
  +            name = def.getName();
  +            autoCreate = def.isAutoCreate();
  +            onVersion = def.getOnVersion();
  +            readOnly = def.isReadOnly();
  +            this.definingObjectClass = definingObjectClass;
  +            node = true;
  +        }
  +
  +        ElemDef(PropertyDef def, String definingObjectClass) {
  +            name = def.getName();
  +            autoCreate = def.isAutoCreate();
  +            onVersion = def.getOnVersion();
  +            readOnly = def.isReadOnly();
  +            this.definingObjectClass = definingObjectClass;
  +            node = false;
  +        }
  +
  +        String getDefiningObjectClass() {
  +            return definingObjectClass;
  +        }
  +
  +        String getName() {
  +            return name;
  +        }
  +
  +        boolean isAutoCreate() {
  +            return autoCreate;
  +        }
  +
  +        int getOnVersion() {
  +            return onVersion;
  +        }
  +
  +        boolean isReadOnly() {
  +            return readOnly;
  +        }
  +
  +        boolean isNode() {
  +            return node;
  +        }
       }
   
  -    void merge(EffectiveObjectClass eoc) throws ConstraintViolationException {
  -        // @todo implement
  -        mergedOCs.add(eoc);
  +    class NodeDef extends ElemDef {
  +        protected final String[] objectClassConstraint;
  +        protected final String[] defaultObjectClasses;
  +
  +        NodeDef(ChildNodeDef def, String definingObjectClass) {
  +            super(def, definingObjectClass);
  +            defaultObjectClasses = def.getDefaultObjectClasses();
  +            objectClassConstraint = def.getObjectClassConstraint();
  +        }
  +
  +        String[] getDefaultObjectClasses() {
  +            return defaultObjectClasses;
  +        }
  +
  +        String[] getObjectClassConstraint() {
  +            return objectClassConstraint;
  +        }
       }
   
  -    boolean contains(String ocName) {
  -        return false;
  +    class PropDef extends ElemDef {
  +        protected final int type;
  +        protected final Value defaultValue;
  +        protected final String valueConstraint;
  +        protected final boolean mandatory;
  +
  +        PropDef(PropertyDef def, String definingObjectClass) {
  +            super(def, definingObjectClass);
  +            type = def.getType();
  +            defaultValue = def.getDefaultValue();
  +            valueConstraint = def.getValueConstraint();
  +            mandatory = def.isMandatory();
  +        }
  +
  +        Value getDefaultValue() {
  +            return defaultValue;
  +        }
  +
  +        int getType() {
  +            return type;
  +        }
  +
  +        boolean isMandatory() {
  +            return mandatory;
  +        }
  +
  +        String getValueConstraint() {
  +            return valueConstraint;
  +        }
       }
   }
  
  
  
  1.5       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementImpl.java
  
  Index: ElementImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  
  
  
  1.4       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementListener.java
  
  Index: ElementListener.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementListener.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  
  
  
  1.5       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementManager.java
  
  Index: ElementManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  
  
  
  1.4       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementManagerSupport.java
  
  Index: ElementManagerSupport.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ElementManagerSupport.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  
  
  
  1.5       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/HierarchyNode.java
  
  Index: HierarchyNode.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/HierarchyNode.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  
  
  
  1.4       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/IteratorHelper.java
  
  Index: IteratorHelper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/IteratorHelper.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  
  
  
  1.6       +5 -5      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java
  
  Index: NodeImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- NodeImpl.java     3 Jun 2003 12:31:55 -0000       1.5
  +++ NodeImpl.java     6 Jun 2003 17:28:23 -0000       1.6
  @@ -1444,7 +1444,7 @@
        */
       public void remove(Element element)
               throws InvalidPathException, AccessDeniedException, 
ConstraintViolationException, RepositoryException {
  -        // @todo handle version nodes and hardlinks
  +        // @todo handle version nodes and hardlonks
           elemMgr.removeElement(element.getPath());
       }
   
  
  
  
  1.6       +4 -5      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/PropertyImpl.java
  
  Index: PropertyImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/PropertyImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- PropertyImpl.java 2 Jun 2003 12:33:08 -0000       1.5
  +++ PropertyImpl.java 6 Jun 2003 17:28:23 -0000       1.6
  @@ -480,7 +480,6 @@
                    // @todo determine length of binary data
                    return -1;
            }
  -
        } catch (RepositoryException e) {
            log.error("failed to determine property length", e);
        }
  
  
  
  1.4       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryFactory.java
  
  Index: RepositoryFactory.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryFactory.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  
  
  
  1.4       +13 -4     
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java
  
  Index: RepositoryImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- RepositoryImpl.java       30 May 2003 13:22:36 -0000      1.3
  +++ RepositoryImpl.java       6 Jun 2003 17:28:23 -0000       1.4
  @@ -81,6 +81,8 @@
   
       private final FileSystem fs;
   
  +    private ObjectClassManagerImpl ocMgr;
  +
       /**
        * Package private constructor
        *
  @@ -93,6 +95,13 @@
       ElementManager getElementManager(TicketImpl ticket) {
           // @todo implement synchronization of different per-ticket element managers
           return new ElementManager(fs, ticket);
  +    }
  +
  +    synchronized ObjectClassManagerImpl getObjectClassManager() {
  +        if (ocMgr == null) {
  +            ocMgr = new ObjectClassManagerImpl();
  +        }
  +        return ocMgr;
       }
   
       //-----------------------------------------------------------< Repository >
  
  
  
  1.5       +0 -0      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RootContentNode.java
  
  Index: RootContentNode.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RootContentNode.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  
  
  
  1.4       +5 -6      
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java
  
  Index: TicketImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TicketImpl.java   30 May 2003 13:22:36 -0000      1.3
  +++ TicketImpl.java   6 Jun 2003 17:28:23 -0000       1.4
  @@ -253,8 +253,7 @@
           if (impersonator != null) {
               return impersonator.getObjectClassManager();
           }
  -        // @todo implement objectclass support
  -        throw new UnsupportedRepositoryOperationException();
  +        return rep.getObjectClassManager();
       }
   
       /**
  
  
  
  1.1                  
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ObjectClassDefImpl.java
  
  Index: ObjectClassDefImpl.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ObjectClassDefImpl.java,v
 1.1 2003/06/06 17:28:23 stefan Exp $
   * $Revision: 1.1 $
   * $Date: 2003/06/06 17:28:23 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.slide.jcr.core;
  
  import org.apache.log4j.Logger;
  
  import javax.jcr.Node;
  import javax.jcr.RepositoryException;
  import javax.jcr.objectclass.*;
  
  
  /**
   * An <code>ObjectClassDefImpl</code> ...
   *
   * @version $Revision: 1.1 $, $Date: 2003/06/06 17:28:23 $
   * @author Stefan Guggisberg
   * @since
   */
  class ObjectClassDefImpl implements ObjectClassDef {
  
      private static Logger log = Logger.getLogger(ObjectClassDefImpl.class);
  
      private final ObjectClassManagerImpl ocMgr;
  
      private final Node node;
  
      private String name;
  
      private boolean registered;
  
      private ObjectClass oc;
  
      /**
       * Package private constructor
       */
      ObjectClassDefImpl(ObjectClassManagerImpl ocMgr, Node node) {
          this.ocMgr = ocMgr;
          this.node = node;
          try {
              name = node.getProperty("jcr:Name").toString();
          } catch (RepositoryException e) {
              name = "";
          }
          if (name.length() > 0) {
              try {
                  oc = this.ocMgr.getObjectClass(name);
                  registered = true;
              } catch (NoSuchObjectClassException e) {
                  registered = false;
              }
          } else {
              registered = false;
          }
      }
  
      //-------------------------------------------------------< ObjectClassDef >
      /**
       * @see ObjectClassDef#getChildNodeDefs
       */
      public ChildNodeDef[] getChildNodeDefs() throws RepositoryException {
          // @todo implement getChildNodeDefs
          return new ChildNodeDef[0];
      }
  
      /**
       * @see ObjectClassDef#getDefinitionNode
       */
      public Node getDefinitionNode() throws RepositoryException {
          // @todo implement getDefinitionNode
          return null;
      }
  
      /**
       * @see ObjectClassDef#getName
       */
      public String getName() throws RepositoryException {
          return name;
      }
  
      /**
       * @see ObjectClassDef#getPropertyDefs
       */
      public PropertyDef[] getPropertyDefs() throws RepositoryException {
          // @todo implement getPropertyDefs
          return new PropertyDef[0];
      }
  
      /**
       * @see ObjectClassDef#getRegisteredObjectClass
       */
      public ObjectClass getRegisteredObjectClass() {
          return oc;
      }
  
      /**
       * @see ObjectClassDef#getSuperclasses
       */
      public String[] getSuperclasses() throws RepositoryException {
          // @todo implement getSuperclasses
          return new String[0];
      }
  
      /**
       * @see ObjectClassDef#register
       */
      public ObjectClass register() throws InvalidObjectClassDefException, 
ObjectClassExistsException, RepositoryException {
          // @todo implement register
          return null;
      }
  
      /**
       * @see ObjectClassDef#setChildNodeDefs
       */
      public void setChildNodeDefs(ChildNodeDef[] defs) throws 
ObjectClassRegisteredException, RepositoryException {
          // @todo implement setChildNodeDefs
      }
  
      /**
       * @see ObjectClassDef#setName
       */
      public void setName(String name) throws ObjectClassRegisteredException, 
RepositoryException {
          // @todo implement setName
      }
  
      /**
       * @see ObjectClassDef#setPropertyDefs
       */
      public void setPropertyDefs(PropertyDef[] defs) throws 
ObjectClassRegisteredException, RepositoryException {
          // @todo implement setPropertyDefs
      }
  
      /**
       * @see ObjectClassDef#setSuperclasses
       */
      public void setSuperclasses(String[] names) throws 
ObjectClassRegisteredException, RepositoryException {
          // @todo implement setSuperclasses
      }
  }
  
  
  
  1.4       +34 -55    
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ObjectClassImpl.java
  
  
  
  
  1.1                  
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ObjectClassManagerImpl.java
  
  Index: ObjectClassManagerImpl.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ObjectClassManagerImpl.java,v
 1.1 2003/06/06 17:28:23 stefan Exp $
   * $Revision: 1.1 $
   * $Date: 2003/06/06 17:28:23 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.slide.jcr.core;
  
  import org.apache.log4j.Logger;
  
  import javax.jcr.*;
  import javax.jcr.access.AccessDeniedException;
  import javax.jcr.objectclass.*;
  import java.util.*;
  
  /**
   * A <code>ObjectClassManagerImpl</code> ...
   *
   * @version $Revision: 1.1 $, $Date: 2003/06/06 17:28:23 $
   * @author Stefan Guggisberg
   * @since
   */
  class ObjectClassManagerImpl implements ObjectClassManager {
      private static Logger log = Logger.getLogger(ObjectClassManagerImpl.class);
  
      // cache of pre-build aggregations of object classes
      private final TreeMap aggregates;
  
      /**
       * Package private constructor
       */
      ObjectClassManagerImpl() {
          aggregates = new TreeMap();
      }
  
      /**
       *
       * @param ocNames
       * @return
       */
      synchronized EffectiveObjectClass getEffectiveObjectClass(String[] ocNames)
              throws ConstraintViolationException, NoSuchObjectClassException, 
RepositoryException {
          EffectiveObjectClass result = EffectiveObjectClass.create(this);
  
          WeightedKey key = new WeightedKey(ocNames);
  
          // short-cut for optimization
          if (aggregates.containsKey(key)) {
              return (EffectiveObjectClass) aggregates.get(key);
          }
  
          // build list of 'best' existing sub-aggregates
          ArrayList tmpResults = new ArrayList();
          while (key.size() > 0) {
              // check if we've already build this aggregate
              if (aggregates.containsKey(key)) {
                  tmpResults.add(aggregates.get(key));
                  // subtract the result from the temporary key
                  // (which is 'empty' now)
                  key = key.subtract(key);
                  break;
              }
              // walk list of existing aggregates sorted by 'weight' of
              // aggregate (i.e. the cost of building it)
              boolean foundSubResult = false;
              Iterator iter = aggregates.keySet().iterator();
              while (iter.hasNext()) {
                  WeightedKey k = (WeightedKey) iter.next();
                  if (key.contains(k)) {
                      tmpResults.add(aggregates.get(k));
                      // subtract the result from the temporary key
                      key = key.subtract(k);
                      foundSubResult = true;
                      break;
                  }
              }
              if (!foundSubResult) {
                  // no matching sub-aggregates found:
                  // build aggregate of remaining object classes
                  String[] remainder = key.toArray();
                  for (int i = 0; i < remainder.length; i++) {
                      result = result.merge(remainder[i]);
                      // add to result list
                      tmpResults.add(result);
                      // store intermediate result
                      WeightedKey k = new WeightedKey(new String[]{remainder[i]});
                      aggregates.put(k, result);
                  }
                  break;
              }
          }
          // merge the sub-aggregates into new effective objectclass
          for (int i = 0; i < tmpResults.size(); i++) {
              result = result.merge((EffectiveObjectClass) tmpResults.get(i));
              // store intermediate result
              WeightedKey k = new WeightedKey(result.getMergedObjectClasses());
              aggregates.put(k, result);
          }
          // we're done
          return result;
      }
  
      //---------------------------------------------------< ObjectCLassManager >
      /**
       * @see ObjectClassManager#createObjectClassDef
       */
      public ObjectClassDef createObjectClassDef(String absPath) throws 
InvalidPathException, ElementExistsException, ConstraintViolationException, 
AccessDeniedException, RepositoryException {
          // @todo implement createObjectClassDef
          return null;
      }
  
      /**
       * @see ObjectClassManager#getAllObjectClasses
       */
      public ObjectClassIterator getAllObjectClasses() throws RepositoryException {
          // @todo implement getAllObjectClasses
          return new IteratorHelper(Collections.EMPTY_LIST.iterator());
      }
  
      /**
       * @see ObjectClassManager#getObjectClass
       */
      public ObjectClass getObjectClass(String name) throws NoSuchObjectClassException 
{
          // @todo implement getObjectClass
          return null;
      }
  
      /**
       * @see ObjectClassManager#getObjectClassDef
       */
      public ObjectClassDef getObjectClassDef(Node node) throws 
ConstraintViolationException, RepositoryException {
          // @todo implement getObjectClassDef
          return null;
      }
  
      //--------------------------------------------------------< inner classes >
      /**
       * A <code>WeightedKey</code> uniquely identifies
       * a combination (i.e. an aggregation) of one or more objectclasses.
       * The weight is an indicator for the cost involved in building such an
       * aggregate (an aggregation multiple complex objectclasses with deep
       * inheritance trees is more costly to build/validate than an agreggation
       * of two very simple objectclasses with just one property definition each).
       * A very simple (and not very accurate) approximation of the weight would
       * be the number of aggreagted objectclasses (ignoring inheritance and
       * complexity of each involved objectclass).
       * <p>
       * The more accurate the weight definition, the more efficient is the
       * the building of new aggregates.
       * <p>
       * Let's assume we have an aggregation of objectclasses named "b", "a" and "c".
       * Its key would be "[a][b][c]", the pattern ".*[a].*[b].*[c].*" and the weight 
3.
       *
       * @author Stefan Guggisberg
       */
      static class WeightedKey implements Comparable {
          private final TreeSet set;
          private final int weight;
  
          /**
           *
           * @param ocNames
           */
          WeightedKey(String[] ocNames) {
              this(ocNames, ocNames.length);
          }
  
          /**
           *
           * @param ocNames
           * @param weight
           */
          WeightedKey(String[] ocNames, int weight) {
              this.weight = weight;
  
              set = new TreeSet();
              for (int i = 0; i < ocNames.length; i++) {
                  // add name to this sorted set
                  set.add(ocNames[i]);
              }
          }
  
          /**
           *
           * @param ocNames
           */
          WeightedKey(Collection ocNames) {
              this(ocNames, ocNames.size());
          }
  
          /**
           *
           * @param ocNames
           * @param weight
           */
          WeightedKey(Collection ocNames, int weight) {
              this.weight = weight;
              set = new TreeSet(ocNames);
          }
  
          /**
           * The key is the string representation of this sorted set
           * (e.g. the key for a set containing entries "c", "b" and "a" would
           * be "[a], [b], [c]").
           *
           * @see AbstractCollection#toString
           *
           * @return string representation of this sorted set
           */
          String getKey() {
              return set.toString();
          }
  
          /**
           *
           * @return
           */
          int getWeight() {
              return weight;
          }
  
          int size() {
              return set.size();
          }
  
          Iterator iterator() {
              return Collections.unmodifiableSortedSet(set).iterator();
          }
  
          Set getSet() {
              return Collections.unmodifiableSortedSet(set);
          }
  
          String[] toArray() {
              return (String[]) set.toArray(new String[set.size()]);
          }
  
          boolean contains(WeightedKey otherKey) {
              return set.containsAll(otherKey.getSet());
          }
  
          WeightedKey subtract(WeightedKey otherKey) {
              Set tmp = (Set) set.clone();
              tmp.removeAll(otherKey.getSet());
              return new WeightedKey(tmp);
  
          }
  
          /**
           * The resulting sort-order is: 1. descending weight, 2. ascending key
           * (i.e. string representation of this sorted set).
           * @param o
           * @return
           */
          public int compareTo(Object o) {
              WeightedKey other = (WeightedKey) o;
              if (getWeight() > other.getWeight()) {
                  return -1;
              } else if (getWeight() < other.getWeight()) {
                  return 1;
              }
              return getKey().compareTo(other.getKey());
          }
      }
  }
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to