You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/07/13 15:26:06 UTC

svn commit: r793581 [9/23] - in /felix/trunk/sigil: ./ bld-ivy/ bld-ivy/example/ bld-ivy/example/dependence/ bld-ivy/example/dependence/dependee/ bld-ivy/example/dependence/dependee/src/ bld-ivy/example/dependence/dependee/src/standalone/ bld-ivy/examp...

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ICompoundModelElement.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ICompoundModelElement.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ICompoundModelElement.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ICompoundModelElement.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,38 @@
+/*
+ * 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.cauldron.sigil.model;
+
+import java.util.Set;
+
+public interface ICompoundModelElement extends IModelElement {
+    boolean addChild(IModelElement children) throws InvalidModelException;
+    
+    boolean removeChild(IModelElement children);
+    
+    IModelElement[] children();
+    
+    void visit(IModelWalker walker);
+    
+    <T extends IModelElement> T[] childrenOfType( Class<T> type );
+    
+    Set<Class<? extends IModelElement>> getRequiredChildren();
+    
+    Set<Class<? extends IModelElement>> getOptionalChildren();    
+}
\ No newline at end of file

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependency.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependency.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependency.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependency.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,24 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public interface IDependency extends IModelElement {
+	IDependent getDependent();
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependent.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependent.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependent.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependent.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,24 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public interface IDependent extends IModelElement {
+	IDependency getDepender();
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependentModelElement.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependentModelElement.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependentModelElement.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IDependentModelElement.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,37 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public interface IDependentModelElement extends IModelElement {
+    /**
+     * @return
+     */
+    IDependency[] getDependencies();
+    
+    /**
+     * @param dependency
+     */
+    void addDependency(IModelElement dependency);
+    
+    /**
+     * @param dependency
+     */
+    void removeDependency(IModelElement dependency);
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelElement.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelElement.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelElement.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelElement.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,98 @@
+/*
+ * 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.cauldron.sigil.model;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Descriptors represent static information about component, composite or system. They allow other services to decide
+ * how to deal with the given entity without the need to directly interact with the entity.
+ * 
+ * @author dave
+ * 
+ */
+public interface IModelElement extends Cloneable {
+    /**
+     * A brief human readable description of the component, composite or system.
+     * 
+     * @return
+     */
+    String getElementDescription();
+    
+    /**
+     * A set of key value pairs designed for use by a machine to classify a particular component, composite or system.
+     * 
+     * @return
+     */
+    Map<Object, Object> getMeta();
+
+    /**
+     * Set meta data on this descriptor. Meta data is designed for use by a machine to classify or further enhance a
+     * particular component, composite or system.
+     * 
+     * @param meta
+     */
+    void setMeta(Map<Object, Object> meta);
+
+    /**
+     * Check to see if this descriptor defines a complete set of properties. The definition of what constitutes a
+     * complete set is up to the implementing class.
+     * 
+     * @throws InvalidModelException
+     */
+    void checkValid() throws InvalidModelException;
+    
+    /**
+     * Find the parent element of this model element or null if no parent exists.
+     * @return
+     */
+    IModelElement getParent();
+    
+    void setParent( IModelElement parent );
+        
+    /**
+     * Finds the first ancestor up the hierarch of parents which is an instance of the specified
+     * type.
+     * 
+     * @param type
+     * @return
+     */
+    <T extends IModelElement> T getAncestor(Class<T> type);
+    
+    IModelElement clone();
+    
+    Set<String> getPropertyNames();
+    
+    void setProperty(String name, Object value) throws NoSuchMethodException;
+    
+	void addProperty(String name, Object value) throws NoSuchMethodException;
+	
+	void removeProperty(String name, Object value) throws NoSuchMethodException;
+	
+    Object getProperty(String name) throws NoSuchMethodException;
+    
+    Object getDefaultPropertyValue(String name);
+    
+    Set<String> getRequiredProperties();
+
+	Class<?> getPropertyType(String name) throws NoSuchMethodException;
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelInfo.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelInfo.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelInfo.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,26 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public interface IModelInfo {
+	String getGroupName();
+	String getGroupURI();
+	String getName();
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelWalker.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelWalker.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelWalker.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IModelWalker.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,25 @@
+/*
+ * 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.cauldron.sigil.model;
+
+
+public interface IModelWalker {
+	boolean visit( IModelElement element );
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/INamedModelElement.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/INamedModelElement.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/INamedModelElement.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/INamedModelElement.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,27 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public interface INamedModelElement extends IModelElement {
+	void setName(String name);
+	String getName();
+    OverrideOptions getOverride();
+    void setOverride(OverrideOptions override);	
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IRequirementModelElement.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IRequirementModelElement.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IRequirementModelElement.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/IRequirementModelElement.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,24 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public interface IRequirementModelElement {
+	boolean accepts(IModelElement provider);
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/InvalidModelException.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/InvalidModelException.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/InvalidModelException.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/InvalidModelException.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,45 @@
+/*
+ * 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.cauldron.sigil.model;
+
+/**
+ * @author dave
+ * 
+ */
+public class InvalidModelException extends RuntimeException {
+	
+	private static final long serialVersionUID = 1L;
+	
+	private IModelElement target;
+	
+    public InvalidModelException(IModelElement target, String msg) {
+        super(msg);
+        this.target = target;
+    }
+
+    public InvalidModelException(IModelElement target, String msg, Throwable t) {
+        super(msg, t);
+        this.target = target;
+    }
+    
+    public IModelElement getTarget() {
+    	return target;
+    }
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactory.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactory.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactory.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,168 @@
+/*
+ * 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.cauldron.sigil.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class ModelElementFactory {
+	static class ElementInfo {
+		Class<? extends IModelElement> implType;
+		String name;
+		String groupName;
+		String groupURI;
+		
+		public ElementInfo(Class<? extends IModelElement> implType, String name, String groupName, String groupURI) {
+			this.implType = implType;
+			this.name = name;
+			this.groupName = groupName;
+			this.groupURI = groupURI;
+		}
+		
+		public Class<? extends IModelElement> getImplType() {
+			return implType;
+		}
+		public String getName() {
+			return name;
+		}
+		
+		public String getGroupName() {
+			return groupName;
+		}
+
+		public String getGroupURI() {
+			return groupURI;
+		}
+		
+		public String toString() {
+			return "ElementInfo[" + name + ":" + groupName + ":" + groupURI + ":" + implType.getCanonicalName() + "]";
+		}
+	}
+
+	static class ModelInfo implements IModelInfo {
+
+		private ElementInfo e;
+		
+		public ModelInfo(ElementInfo e) {
+			this.e = e;
+		}
+
+		public String getGroupName() {
+			return e.getGroupName();
+		}
+
+		public String getGroupURI() {
+			return e.getGroupURI();
+		}
+
+		public String getName() {
+			return e.getName();
+		}
+
+	}
+
+	static class DefaultModelElementFactory extends ModelElementFactory {
+		private HashMap<Class<? extends IModelElement>, ElementInfo> elementInfo = new HashMap<Class<? extends IModelElement>, ElementInfo>();
+		
+		@SuppressWarnings("unchecked")
+		@Override
+		public <T extends IModelElement> T newModelElement( Class<T> type ) throws ModelElementFactoryException {
+			ElementInfo info = elementInfo.get( type );
+			if ( info == null ) {
+				throw new ModelElementFactoryException( "No implementation registered for " + type );
+			}
+			try {
+				return (T) info.getImplType().newInstance();
+			} catch (InstantiationException e) {
+				throw new ModelElementFactoryException(e);
+			} catch (IllegalAccessException e) {
+				throw new ModelElementFactoryException(e);
+			}
+		}
+
+		@Override
+		public <T extends IModelElement> void register(Class<T> type, Class<? extends T> impl, String name, String groupName, String groupURI ) {
+			elementInfo.put( type, new ElementInfo( impl, name, groupName, groupURI ) );
+		}
+
+		@Override
+		public <T extends IModelElement> void unregister(Class<T> type,
+				Class<? extends T> impl) {
+			ElementInfo info = elementInfo.get( type );
+			if ( info != null && info.getImplType() == impl ) {
+				elementInfo.remove(type);
+			}
+		}
+
+		@Override
+		public IModelInfo getModelInfo(Class<? extends IModelElement> type) {
+			ElementInfo e = findElementInfo( type );
+			
+			if ( e == null ) {
+				return null;
+			}
+			
+			return new ModelInfo( e );
+		}
+
+		@Override
+		public IModelElement newModelElement(String namespaceURI, String localPart) throws ModelElementFactoryException {
+			for ( Map.Entry<Class<? extends IModelElement>, ElementInfo> e : elementInfo.entrySet() ) {
+				ElementInfo i = e.getValue();
+				if ( equal( namespaceURI, i.getGroupURI() ) && equal( i.getName(), localPart ) ) {
+					return newModelElement(e.getKey());
+				}
+			}
+			
+			return null;
+		}
+
+		private boolean equal(String val1, String val2) {
+			return val1 == null ? val2 == null : val1.equals( val2 );
+		}
+
+		private ElementInfo findElementInfo( Class<? extends IModelElement> type ) {
+			for ( ElementInfo e : elementInfo.values() ) {
+				if ( e.getImplType() == type ) {
+					return e;
+				}
+			}
+			
+			return null;
+		}
+
+	}
+
+	public abstract <T extends IModelElement> T newModelElement( Class<T> type ) throws ModelElementFactoryException;
+	
+	public abstract IModelElement newModelElement(String namespaceURI, String localPart) throws ModelElementFactoryException;	
+	
+	public abstract <T extends IModelElement> void register( Class<T> type, Class<? extends T> impl, String name, String groupName, String groupURI );
+	
+	public abstract <T extends IModelElement> void unregister( Class<T> type, Class<? extends T> impl );
+
+	public abstract IModelInfo getModelInfo( Class<? extends IModelElement> type );
+	
+	private static ModelElementFactory instance = new DefaultModelElementFactory();
+
+	public static ModelElementFactory getInstance() {
+		return instance;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactoryException.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactoryException.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactoryException.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementFactoryException.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,34 @@
+/*
+ * 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.cauldron.sigil.model;
+
+public class ModelElementFactoryException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	public ModelElementFactoryException(Throwable t) {
+		super(t);
+	}
+
+	public ModelElementFactoryException(String msg) {
+		super(msg);
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementSupport.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementSupport.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementSupport.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/ModelElementSupport.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,728 @@
+/*
+ * 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.cauldron.sigil.model;
+
+import java.io.Serializable;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.logging.Logger;
+
+
+public class ModelElementSupport implements Serializable {
+
+	private static final Logger log = Logger.getLogger( ModelElementSupport.class.getName() );
+	
+	private static final long serialVersionUID = 1L;
+	
+	private static final PropertyAdapter[] EMPTY_PROPS = new PropertyAdapter[] {};
+	private static final IModelElement[] EMPTY_ELEMENTS = new IModelElement[] {};
+	private static final Object[] ZERO_ARGS = new Object[] {};
+	private static final Class<?>[] ZERO_PARAMS = new Class[] {};
+	
+	private static final WeakHashMap<Class<?>, SoftReference<ChildAdapter[]>> adapterCache = new WeakHashMap<Class<?>, SoftReference<ChildAdapter[]>>();;	
+	private static final WeakHashMap<Class<?>, SoftReference<PropertyAdapter[]>> propertyCache = new WeakHashMap<Class<?>, SoftReference<PropertyAdapter[]>>();;	
+	
+	private IModelElement target;
+	
+	private transient SoftReference<PropertyAdapter[]> propertyReference;
+	private transient SoftReference<ChildAdapter[]> childrenReference;
+	private transient SoftReference<Set<String>> propertyNameReference;
+	
+	public ModelElementSupport(IModelElement target) {
+		this.target = target;
+	}
+
+	public void setProperty(String name, Object value) throws NoSuchMethodException {
+		PropertyAdapter p = findProperty( name, value );
+		if ( p == null ) {
+			throw new NoSuchMethodException( "No such property " + name + " for type " + target.getClass() );
+		}
+		invoke( target, p.getWriteMethod(), value );
+	}
+	
+	public void addProperty(String name, Object value) throws NoSuchMethodException {
+		PropertyAdapter p = findProperty( name, value );
+		if ( p == null ) {
+			throw new NoSuchMethodException( "No such property " + name + " for type " + target.getClass() );
+		}
+		invoke( target, p.getAddMethod(), value );
+	}
+
+	public void removeProperty(String name, Object value) throws NoSuchMethodException {
+		PropertyAdapter p = findProperty( name, value );
+		if ( p == null ) {
+			throw new NoSuchMethodException( "No such property " + name + " for type " + target.getClass() );
+		}
+		invoke( target, p.getRemoveMethod(), value );
+	}
+	
+	public Object getProperty( String name ) throws NoSuchMethodException {
+		PropertyAdapter p = findProperty( name, null );
+		if ( p == null ) {
+			throw new NoSuchMethodException( "No such property " + name + " for type " + target.getClass() );
+		}
+		return invoke( target, p.getReadMethod(), ZERO_ARGS );
+	}
+	
+	public Set<String> getPropertyNames() {
+		Set<String> names = propertyNameReference == null ? null : propertyNameReference.get();
+		
+		if ( names == null ) {
+			names = new HashSet<String>();
+			
+			PropertyAdapter[] props = cachedProps( target.getClass() );
+			for ( PropertyAdapter prop : props ) {
+				names.add( prop.getName() );
+			}
+			
+			propertyNameReference = new SoftReference<Set<String>>(names);
+		}
+		
+		return names;
+	}
+	
+	public Object getDefaultPropertyValue(String name) {
+		try {
+			Method m = target.getClass().getMethod( makeDefaultPropertyValue( name ), ZERO_PARAMS );
+			return invoke( target, m, ZERO_ARGS );
+		} catch (SecurityException e) {
+			throw new UndeclaredThrowableException(e);
+		} catch (NoSuchMethodException e) {
+			// fine no default
+			return null;
+		}
+	}	
+	
+	public Class<?> getPropertyType(String name) throws NoSuchMethodException {
+		PropertyAdapter p = findProperty( name, null );
+		if ( p == null ) {
+			throw new NoSuchMethodException( "No such property " + name + " for type " + target.getClass() );
+		}
+		return p.getPropertyType();
+	}	
+	
+	@SuppressWarnings("unchecked")
+	public <T extends IModelElement> T[] childrenOfType( Class<T> type ) {
+		ChildAdapter[] adapters = cachedAdapters();
+		
+		if ( adapters.length == 0 ) {
+			// return (T[]) EMPTY_ELEMENTS;
+    		return ((T[])Array.newInstance(type, 0));
+		}
+		
+		ArrayList<T> elements = new ArrayList<T>();
+		
+		for ( ChildAdapter adapter : adapters ) {
+			Collection<? extends IModelElement> val = adapter.members(target);
+			
+			for ( IModelElement e : val ) {
+				if ( type.isInstance(e) ) {
+					elements.add( (T) e );
+				}
+			}
+		}
+		
+		//return elements.toArray( (T[]) EMPTY_ELEMENTS );
+		return elements.toArray((T[])Array.newInstance(type, elements.size()));
+	}
+	
+	public IModelElement[] children() {
+		ChildAdapter[] adapters = cachedAdapters();
+		
+		if ( adapters.length == 0 ) {
+			return EMPTY_ELEMENTS;
+		}
+		
+		ArrayList<IModelElement> elements = new ArrayList<IModelElement>();
+		
+		for ( ChildAdapter adapter : adapters ) {
+			elements.addAll( adapter.members(target) );
+		}
+		
+		return elements.toArray( EMPTY_ELEMENTS );
+	}
+	
+	public boolean addChild(IModelElement element) throws InvalidModelException {
+		if ( element.getParent() == null ) {
+			ChildAdapter[] adapters = cachedAdapters();
+			
+			if ( adapters.length > 0 ) {
+				for ( ChildAdapter adapter : adapters ) {
+					if ( adapter.add( target, element ) ) {
+						element.setParent(target);
+						return true;
+					}
+				}
+			}
+		}
+		
+		return false;
+	}
+	
+	public boolean removeChild(IModelElement element) {
+		if ( element.getParent() == target ) {
+			ChildAdapter[] adapters = cachedAdapters();
+			
+			if ( adapters.length > 0 ) {
+				for ( ChildAdapter adapter : adapters ) {
+					if ( adapter.remove( target, element ) ) {
+						element.setParent( null );
+						return true;
+					}
+				}
+			}
+		}
+		
+		return false;
+	}
+
+	public Set<Class<? extends IModelElement>> getChildrenTypes(boolean required) {
+		ChildAdapter[] adapters = cachedAdapters();
+		
+		if ( adapters.length == 0 ) {
+			return Collections.emptySet();
+		}
+		
+		HashSet<Class<? extends IModelElement>> types = new HashSet<Class<? extends IModelElement>>();
+		
+		for ( ChildAdapter adapter : adapters ) {
+			if ( adapter.isRequired() == required ) {
+				Class<? extends IModelElement> type = adapter.getType();
+				
+				if ( type != null ) {
+					types.add( type );
+				}
+			}
+		}
+		
+		return types;
+	}
+	
+	private PropertyAdapter findProperty(String name, Object value) {
+		PropertyAdapter[] props = propertyReference == null ? null : propertyReference.get();
+		
+		if ( props == null ) {
+			props = cachedProps( target.getClass() );
+			propertyReference = new SoftReference<PropertyAdapter[]>( props );
+		}
+		
+		for ( PropertyAdapter prop : props ) {
+			if ( prop.getName().equals( name ) && (value == null || prop.getRawType().isAssignableFrom(value.getClass() ) ) ) {
+				return prop;
+			}
+		}
+		
+		return null;
+	}
+
+	private static PropertyAdapter[] cachedProps(
+			Class<? extends IModelElement> type) {
+		SoftReference<PropertyAdapter[]> ref = propertyCache.get( type );
+		
+		PropertyAdapter[] props = ref == null ? null : ref.get();
+		
+		if ( props == null ) {
+			props = loadProps( type );
+			propertyCache.put( type, new SoftReference<PropertyAdapter[]>( props ) );
+		}
+		
+		return props;
+	}
+
+	private static PropertyAdapter[] loadProps(Class<? extends IModelElement> type) {
+		ArrayList<PropertyAdapter> props = new ArrayList<PropertyAdapter>();
+		for ( Method m : type.getMethods() ) {
+			if ( isValidProperty( m )) {
+				try {
+					PropertyAdapter p = new PropertyAdapter( m, type );
+					props.add( p );
+				} catch (NoSuchMethodException e) {
+					// fine not a bean method
+					log.finer( "Invalid bean property method " + m + ": " + e.getMessage() );
+				}
+			}
+		}
+		
+		return props.toArray( EMPTY_PROPS );
+	}
+
+	private static boolean isValidProperty(Method m) {
+		return m.getName().startsWith( "get" ) && m.getParameterTypes().length == 0 && !m.getDeclaringClass().equals( Object.class ) && !IModelElement.class.isAssignableFrom(m.getReturnType());
+	}
+
+	private static String makeDefaultPropertyValue(String name) {
+		return "getDefault" + capitalise( name );
+	}
+
+	private static String capitalise(String name) {
+		return Character.toUpperCase(name.charAt(0))  + name.substring(1);
+	}
+
+	private static String decapitalise(String substring) {
+		return Character.toLowerCase(substring.charAt(0)) + substring.substring(1);
+	}
+
+	private ChildAdapter[] cachedAdapters() {
+		ChildAdapter[] adapters = childrenReference == null ? null : childrenReference.get();
+		
+		if ( adapters == null ) {
+			adapters = loadAdapters( target );
+			childrenReference = new SoftReference<ChildAdapter[]>( adapters );
+		}		
+		
+		return adapters;
+	}
+	
+	private static ChildAdapter[] loadAdapters(IModelElement target) {
+		Class<? extends IModelElement> type = target.getClass();
+		SoftReference<ChildAdapter[]> ref = adapterCache.get( type );
+		
+		ChildAdapter[] adapters = ref == null ? null : ref.get();
+		
+		if ( adapters == null ) {
+			adapters = buildAdapters( type );
+			adapterCache.put( type, new SoftReference<ChildAdapter[]>( adapters ) );
+		}
+		
+		return adapters;
+	}
+	
+	private static ChildAdapter[] buildAdapters(Class<? extends IModelElement> type) {
+		ArrayList<ChildAdapter> adapters = new ArrayList<ChildAdapter>();
+		
+		for ( Method m : type.getMethods() ) {
+			ChildAdapter adapter = null;
+			
+			if ( isValidGetProperty( m ) ) {
+				adapter = buildGetAdapter( m );
+			}
+			else if ( isValidSetProperty( m ) ) {
+				adapter = buildSetAdapter( m );
+			}
+			else if ( isValidAddProperty( m ) ) {
+				adapter = buildAddAdapter( m );
+			}
+			else if ( isValidRemoveProperty( m ) ) {
+				adapter = buildRemoveAdapter( m );
+			}
+			
+			if ( adapter != null ) {
+				adapters.add( adapter );
+			}
+		}
+		
+		return adapters.toArray( new ChildAdapter[adapters.size()] );
+	}
+
+	private static ChildAdapter buildGetAdapter(Method m) {
+		if ( IModelElement.class.isAssignableFrom( m.getReturnType() ) ) {
+			return new GetPropertyAdapter( m );
+		}
+		else if ( Collection.class.isAssignableFrom( m.getReturnType() ) ) {
+			return new GetCollectionAdapter( m );
+		}
+		else if ( isModelArray( m.getReturnType() ) ) {
+			return new GetArrayAdapter( m );
+		}
+		else {
+			return null;
+		}
+	}
+	
+	private static ChildAdapter buildSetAdapter(Method m) {
+		if ( IModelElement.class.isAssignableFrom( m.getParameterTypes()[0] ) ) {
+			return new SetPropertyAdapter( m );
+		}
+		else {
+			return null;
+		}
+	}
+
+	private static ChildAdapter buildAddAdapter(Method m) {
+		if ( IModelElement.class.isAssignableFrom( m.getParameterTypes()[0] ) ) {
+			return new AddPropertyAdapter( m );
+		}
+		else {
+			return null;
+		}
+	}
+
+	private static ChildAdapter buildRemoveAdapter(Method m) {
+		if ( IModelElement.class.isAssignableFrom( m.getParameterTypes()[0] ) ) {
+			return new RemovePropertyAdapter( m );
+		}
+		else {
+			return null;
+		}
+	}
+
+	private static boolean isValidRemoveProperty(Method m) {
+		return m.getParameterTypes().length == 1 && m.getName().startsWith( "remove" ) && !isDeclared( ICompoundModelElement.class, m );
+	}
+
+	private static boolean isValidAddProperty(Method m) {
+		return m.getParameterTypes().length == 1 && m.getName().startsWith( "add" ) && !isDeclared( ICompoundModelElement.class, m );
+	}
+
+	private static boolean isDeclared(Class<? extends IModelElement> element, Method m) {
+		try {
+			element.getMethod( m.getName(), m.getParameterTypes() );
+			return true;
+		} catch (SecurityException e) {
+			throw new UndeclaredThrowableException( e );
+		} catch (NoSuchMethodException e) {
+			return false;
+		}
+	}
+
+	private static boolean isValidSetProperty(Method m) {
+		return m.getParameterTypes().length == 1 && m.getName().startsWith( "set" ) && !isDeclared( IModelElement.class, m );
+	}
+
+	private static boolean isValidGetProperty(Method m) {
+		return m.getParameterTypes().length == 0 && m.getName().startsWith( "get" ) && !isDeclared( IModelElement.class, m ) && !isDeclared(ICompoundModelElement.class, m);
+	}
+
+	private static Object invoke( Object target, Method m, Object... args ) {
+		try {
+			return m.invoke(target, args);
+		} catch (IllegalArgumentException e) {
+			// this should already have been tested
+			throw new IllegalStateException(e);
+		} catch (IllegalAccessException e) {
+			throw new UndeclaredThrowableException( e );
+		} catch (InvocationTargetException e) {
+			throw new UndeclaredThrowableException( e.getCause() );
+		}
+	}		
+
+	private static class PropertyAdapter {
+
+		String prop;
+		String name;
+		Method g;
+		Method s;
+		Method a;
+		Method r;
+		Class<?> propertyType;
+		
+		public PropertyAdapter(Method g, Class<?> type) throws SecurityException, NoSuchMethodException {
+			if ( g.getReturnType().isArray() || Iterable.class.isAssignableFrom(g.getReturnType() ) ) {
+				prop = g.getName().substring(3);
+				// remove trailing s - as in addWibble, removeWibble, getWibbles
+				prop = prop.substring(0, prop.length() - 1);
+				name = decapitalise( prop );
+				a = find( "add", prop, g.getReturnType(), type );
+				propertyType = a.getParameterTypes()[0];
+				r = find( "remove", prop, g.getReturnType(), type );
+				if ( r.getParameterTypes()[0] != propertyType ) {
+					throw new NoSuchMethodException( "Add remove property method types do not match" );
+				}
+				propertyType = Array.newInstance(propertyType, 0).getClass();
+			}
+			else {
+				prop = g.getName().substring(3);
+				name = decapitalise( prop );
+				propertyType = g.getReturnType();
+				s = find( "set", prop, propertyType, type );
+			}
+			
+			this.g = g;
+		}
+		
+		public Class<?> getRawType() {
+			return propertyType.isArray() ? propertyType.getComponentType() : propertyType;
+		}
+
+		public Class<?> getPropertyType() {
+			return propertyType;
+		}
+
+		public Method getReadMethod() {
+			return g;
+		}
+
+		public Method getAddMethod() throws NoSuchMethodException {
+			if ( a == null ) {
+				throw new NoSuchMethodException( "No such method add" + prop ); 
+			}
+			
+			return a;
+		}
+
+		public Method getRemoveMethod() throws NoSuchMethodException {
+			if ( r == null ) {
+				throw new NoSuchMethodException( "No such method remove" + prop ); 
+			}
+			
+			return r;
+		}
+
+		public Method getWriteMethod() throws NoSuchMethodException {
+			if ( s == null ) {
+				throw new NoSuchMethodException( "No such method set" + prop ); 
+			}
+			
+			return s;
+		}
+		
+		@Override
+		public String toString() {
+			return "PropertyAdapter[" + name + "]";
+		}
+
+		private Method find(String prefix, String prop, Class<?> returnType, Class<?> type) throws SecurityException, NoSuchMethodException {
+			String methodName = prefix + prop;
+			
+			if ( returnType.isArray() ) {
+				Class<?> t = returnType.getComponentType();
+				return type.getMethod( methodName, new Class[] { t } );
+			}
+			else if ( Iterable.class.isAssignableFrom( returnType ) ) {
+				Method f = null;
+				for ( Method m : type.getMethods() ) {
+					if ( m.getParameterTypes().length == 1 && m.getName().equals( methodName ) && !IModelElement.class.isAssignableFrom(m.getParameterTypes()[0]) ) {
+						if ( f == null ) {
+							f = m;
+						}
+						else {
+							throw new NoSuchMethodException( "Found duplicate " + methodName );
+						}
+					}
+				}
+				if ( f == null ) {
+					throw new NoSuchMethodException( "No such method " + methodName );
+				}
+				
+				return f;
+			}
+			else {
+				return type.getMethod( methodName, new Class[] { returnType } ); 
+			}
+		}
+		public String getName() {
+			return name;
+		}
+		
+	}
+	
+	private static abstract class ChildAdapter {
+		Method m;
+		
+		ChildAdapter( Method m ) {
+			this.m = m;
+		}
+		
+		public boolean isRequired() {
+			return m.isAnnotationPresent(Required.class);
+		}
+
+		boolean add(Object target, IModelElement element) {
+			return false;
+		}
+
+		abstract Class<? extends IModelElement> getType();
+
+		boolean remove(Object target, IModelElement element) {
+			return false;
+		}
+
+		Collection<? extends IModelElement> members(Object target) {
+			return Collections.emptyList();
+		}
+
+		@Override
+		public String toString() {
+			return "ChildAdapter[ " + m.getName() + "]";
+		}	
+	}
+	
+	private static class GetPropertyAdapter extends ChildAdapter {
+		GetPropertyAdapter(Method m) {
+			super(m);
+		}
+
+		@Override
+		Collection<? extends IModelElement> members(Object target) {
+			IModelElement member = (IModelElement) invoke( target, m, ZERO_ARGS );
+			if ( member == null ) {
+				return Collections.emptyList();
+			}
+			else {
+				return Collections.<IModelElement>singleton( member );
+			}
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		Class<? extends IModelElement> getType() {
+			return (Class<? extends IModelElement>) m.getReturnType();
+		}
+	}	
+	
+	private static class GetCollectionAdapter extends ChildAdapter {
+		public GetCollectionAdapter(Method m) {
+			super(m);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		Collection<? extends IModelElement> members(Object target) {
+			Collection members = (Collection) invoke( target, m, ZERO_ARGS );
+			if ( members == null ) {
+				return Collections.emptyList();
+			}
+			else {
+				ArrayList<IModelElement> safe = new ArrayList<IModelElement>(members.size());
+				for ( Object o : members ) {
+					if ( o instanceof IModelElement ) {
+						safe.add( (IModelElement) o );
+					}
+				}
+				return safe;
+			}
+		}
+		
+		@Override
+		Class<? extends IModelElement> getType() {
+			// impossible to get type of a collection as erasure removes generics info
+			return null;
+		}		
+		
+	}
+	
+	private static class GetArrayAdapter extends ChildAdapter {
+		public GetArrayAdapter(Method m) {
+			super(m);
+		}
+
+		@Override
+		Collection<? extends IModelElement> members(Object target) {
+			IModelElement[] array = (IModelElement[]) invoke( target, m, ZERO_ARGS );
+			if ( array == null || array.length == 0) {
+				return Collections.emptyList();
+			}
+			else {
+				return (Collection<? extends IModelElement>) Arrays.asList( array );
+			}
+		}
+		
+		@SuppressWarnings("unchecked")
+		@Override
+		Class<? extends IModelElement> getType() {
+			return (Class<? extends IModelElement>) m.getReturnType().getComponentType();
+		}
+	}
+	
+	private static class SetPropertyAdapter extends ChildAdapter {
+		public SetPropertyAdapter(Method m) {
+			super(m);
+		}
+
+		@Override
+		boolean add(Object target, IModelElement element) {
+			if ( m.getParameterTypes()[0].isAssignableFrom( element.getClass() ) ) {
+				invoke(target, m, new Object[] { element } );
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
+
+		@Override
+		boolean remove(Object target, IModelElement element) {
+			if ( m.getParameterTypes()[0].isAssignableFrom( element.getClass() ) ) {
+				invoke(target, m, new Object[] { null } );
+				return true;
+			}
+			else {
+				return false;
+			}
+		}		
+		
+		@SuppressWarnings("unchecked")
+		@Override
+		Class<? extends IModelElement> getType() {
+			return (Class<? extends IModelElement>) m.getParameterTypes()[0];
+		}		
+	}	
+	
+	private static class AddPropertyAdapter extends ChildAdapter {
+		public AddPropertyAdapter(Method m) {
+			super(m);
+		}
+
+		@Override
+		boolean add(Object target, IModelElement element) {
+			if ( m.getParameterTypes()[0].isAssignableFrom( element.getClass() ) ) {
+				invoke(target, m, new Object[] { element } );
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
+		
+		@SuppressWarnings("unchecked")
+		@Override
+		Class<? extends IModelElement> getType() {
+			return (Class<? extends IModelElement>) m.getParameterTypes()[0];
+		}		
+	}
+	
+	private static class RemovePropertyAdapter extends ChildAdapter {
+
+		public RemovePropertyAdapter(Method m) {
+			super(m);
+		}
+
+		@Override
+		boolean remove(Object target, IModelElement element) {
+			if ( m.getParameterTypes()[0].isAssignableFrom( element.getClass() ) ) {
+				invoke(target, m, new Object[] { element } );
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
+		
+		@SuppressWarnings("unchecked")
+		@Override
+		Class<? extends IModelElement> getType() {
+			return (Class<? extends IModelElement>) m.getParameterTypes()[0];
+		}		
+	}
+	
+	private static boolean isModelArray(Class<?> returnType) {
+		return returnType.isArray() && IModelElement.class.isAssignableFrom(returnType.getComponentType() );
+	}
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/OverrideOptions.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/OverrideOptions.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/OverrideOptions.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/OverrideOptions.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,61 @@
+/*
+ * 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.cauldron.sigil.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author dave
+ * 
+ */
+public enum OverrideOptions {
+    NO("no"), MAY("may"), MUST("must");
+
+    private String str;
+
+    private static Map<String, OverrideOptions> map = new HashMap<String, OverrideOptions>();
+
+    static {
+        for (OverrideOptions option : OverrideOptions.values()) {
+            map.put(option.str.toLowerCase(), option);
+        }
+    }
+
+    private OverrideOptions(String str) {
+        this.str = str;
+    }
+
+    public static OverrideOptions parse(String val) {
+        OverrideOptions option = map.get(val.toLowerCase());
+
+        if (option == null) {
+            throw new IllegalArgumentException("Invalid override value " + val);
+        }
+
+        return option;
+    }
+    
+    @Override
+    public String toString() {
+        return str;
+    }
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/Required.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/Required.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/Required.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/Required.java Mon Jul 13 13:25:46 2009
@@ -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.cauldron.sigil.model;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Inherited
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Required {
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/And.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/And.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/And.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/And.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,116 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import java.util.Map;
+
+public class And implements LDAPExpr {
+
+    /**
+     */
+    private static final long serialVersionUID = 1L;
+    private LDAPExpr[] children;
+
+    public static LDAPExpr apply(LDAPExpr... terms) {
+        if (terms == null) {
+            throw new NullPointerException("terms cannot be null");
+        }
+        else if (terms.length == 0) {
+            return Expressions.T;
+        }
+        else if (terms.length == 1) {
+            return terms[0];
+        }
+        LDAPExpr[] filtered = new LDAPExpr[terms.length];
+        int ctr = 0;
+        for (int i = 0; i < terms.length; i++) {
+            if (terms[i].equals(Expressions.F))
+                return Expressions.F;
+            if (terms[i].equals(Expressions.T))
+                continue;
+            filtered[ctr] = terms[i];
+            ctr++;
+        }
+        if (ctr == 0) {
+            return Expressions.T;
+        }
+        else if (ctr == 1) {
+            return filtered[0];
+        }
+        LDAPExpr[] andTerms = new LDAPExpr[ctr];
+        System.arraycopy(filtered, 0, andTerms, 0, ctr);
+
+        return new And(andTerms);
+    }
+
+    private And(LDAPExpr... children) {
+        this.children = children;
+    }
+
+    public boolean eval(Map<String, ?> map) {
+        for (int i = 0; i < children.length; i++) {
+            if (!children[i].eval(map)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public void visit(ExprVisitor v) {
+        v.visitAnd(this);
+    }
+
+    public LDAPExpr[] getChildren() {
+        return children;
+    }
+
+    public void setChildren(LDAPExpr[] children) {
+        this.children = children;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof And) {
+            And that = (And) other;
+            if (children.length != that.children.length) {
+                return false;
+            }
+            for (int i = 0; i < children.length; i++) {
+                if (!children[i].equals(that.children[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer buf = new StringBuffer(256);
+        buf.append("(&");
+        for (int i = 0; i < children.length; i++) {
+            buf.append(" ").append(children[i]).append(" ");
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Cardinality.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Cardinality.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Cardinality.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Cardinality.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,154 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import java.io.Serializable;
+
+/**
+ * Immutable class representing cardinality constraints between two entities.
+ * 
+ */
+public class Cardinality implements Serializable {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+    public static final Cardinality ZERO_TO_MANY = new Cardinality(0, -1);
+    public static final Cardinality ONE_TO_MANY = new Cardinality(1, -1);
+    public static final Cardinality ZERO_TO_ONE = new Cardinality(0, 1);
+    public static final Cardinality ONE_TO_ONE = new Cardinality(1, 1);
+
+    private int min;
+    private int max;
+
+    /**
+     * @param min
+     *            >=0 (usually 0 or 1)
+     * @param max
+     *            >=min or -1 to indicate an unbounded maximum
+     */
+    public Cardinality(int min, int max) {
+        if (min < 0) {
+            throw new IllegalArgumentException("Min cannot be less than 0");
+        }
+
+        if ((max < min) && (max != -1)) {
+            throw new IllegalArgumentException("Max cannot be less than min");
+        }
+
+        this.min = min;
+        this.max = max;
+    }
+
+    public int getMin() {
+        return min;
+    }
+
+    public int getMax() {
+        return max;
+    }
+
+    public String toString() {
+        return min + ".." + ((max == -1) ? ("n") : (Integer.toString(max)));
+    }
+
+    public boolean isDefined(Cardinality cardinality) {
+        return (min <= cardinality.min) && ((max == -1) || (max >= cardinality.max));
+    }
+
+    public boolean isSingleton() {
+        return (min == 1) && (max == 1);
+    }
+
+    public static Cardinality parse(String stringRep) throws IllegalArgumentException {
+        stringRep = stringRep.trim();
+
+        int dotdot = stringRep.indexOf("..");
+
+        if (dotdot == -1) {
+            throw new IllegalArgumentException("Invalid cardinality string representation, expected ..");
+        }
+
+        String minStr = stringRep.substring(0, dotdot);
+        String maxStr = stringRep.substring(dotdot + 2);
+
+        int min = Integer.parseInt(minStr);
+        int max = min;
+
+        if ("n".equals(maxStr)) {
+            max = -1;
+        }
+        else {
+            max = Integer.parseInt(maxStr);
+        }
+
+        return cardinality(min, max);
+    }
+
+    public static Cardinality cardinality(int min, int max) {
+        Cardinality c = null;
+
+        if (min == 0) {
+            if (max == 1) {
+                c = ZERO_TO_ONE;
+            }
+            else if (max == -1) {
+                c = ZERO_TO_MANY;
+            }
+        }
+        else if (min == 1) {
+            if (max == 1) {
+                c = ONE_TO_ONE;
+            }
+            else if (max == -1) {
+                c = ONE_TO_MANY;
+            }
+        }
+
+        if (c == null)
+            c = new Cardinality(min, max);
+
+        return c;
+    }
+
+    public int hashCode() {
+        return max ^ min;
+    }
+
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        try {
+            Cardinality c = (Cardinality) o;
+
+            return (min == c.min) && (max == c.max);
+        }
+        catch (ClassCastException cce) {
+            return false;
+        }
+    }
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/ExprVisitor.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/ExprVisitor.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/ExprVisitor.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/ExprVisitor.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,30 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+public interface ExprVisitor {
+
+    void visitAnd(And a);
+    void visitOr(Or o);
+    void visitNot(Not n);
+    void visitSimple(SimpleTerm st);
+    // if none of the above matches use this
+    void visitAny(LDAPExpr ex);
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Expressions.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Expressions.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Expressions.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Expressions.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,79 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import java.util.Map;
+
+public class Expressions {
+
+    public static LDAPExpr and(LDAPExpr... terms) {
+        return And.apply(terms);
+    }
+
+    public static LDAPExpr or(LDAPExpr... terms) {
+        return Or.apply(terms);
+    }
+
+    public static LDAPExpr not(LDAPExpr e) {
+        return Not.apply(e);
+    }
+
+    public static LDAPExpr T = Bool.TRUE;
+    public static LDAPExpr F = Bool.FALSE;
+
+    // supports direct use of wildcards for ease of testing, but not literal *s
+    public static SimpleTerm ex(String name, Ops op, String rhs) {
+
+        rhs = rhs.replace('*', SimpleTerm.WILDCARD);
+        return new SimpleTerm(name, op, rhs);
+    }
+
+}
+
+class Bool implements LDAPExpr {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+    public static final Bool TRUE = new Bool(true);
+    public static final Bool FALSE = new Bool(false);
+
+    private boolean bool;
+
+    public Bool(boolean bool) {
+        this.bool = bool;
+    }
+
+    public boolean eval(Map<String, ?> map) {
+        return bool;
+    }
+
+    public void visit(ExprVisitor v) {
+    }
+
+    public LDAPExpr[] getChildren() {
+        return CHILDLESS;
+    }
+
+    public String toString() {
+        return "(" + bool + ")";
+    }
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/FilterValidator.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/FilterValidator.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/FilterValidator.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/FilterValidator.java Mon Jul 13 13:25:46 2009
@@ -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.cauldron.sigil.model.common;
+
+public interface FilterValidator {
+
+    public static FilterValidator ACCEPT_ALL = new AcceptEverythingValidator();
+
+    boolean validate(LDAPExpr filter);
+
+    static class AcceptEverythingValidator implements FilterValidator {
+
+        public boolean validate(LDAPExpr filter) {
+            return true;
+        }
+
+    }
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPExpr.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPExpr.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPExpr.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPExpr.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,39 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public interface LDAPExpr extends Serializable {
+
+    public static final LDAPExpr[] CHILDLESS = new LDAPExpr[] {};
+    public static LDAPExpr ACCEPT_ALL = Expressions.T;
+
+    LDAPExpr[] getChildren();
+
+    void visit(ExprVisitor v);
+
+    boolean equals(Object other);
+
+    int hashCode();
+
+    boolean eval(Map<String, ?> map);
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParseException.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParseException.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParseException.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParseException.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,58 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+public class LDAPParseException extends Exception {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    private ParseState ps;
+    private static final String LINE_SEPARATOR = System.getProperty("line.separator", "\\r\\n");
+
+    public LDAPParseException(String message, ParseState ps) {
+        super(message);
+        this.ps = ps;
+    }
+
+    public LDAPParseException(String message) {
+        super(message);
+    }
+
+    @Override
+    public String getMessage() {
+        if (ps == null) {
+            return super.getMessage();
+        }
+
+        String basicMessage = super.getMessage();
+        StringBuffer buf = new StringBuffer(basicMessage.length() + ps.str.length() * 2);
+        buf.append(basicMessage).append(LINE_SEPARATOR);
+        buf.append(ps.str).append(LINE_SEPARATOR);
+        for (int i = 0; i < ps.pos; i++) {
+            buf.append(" ");
+        }
+        buf.append("^");
+        return buf.toString();
+    }
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParser.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParser.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/LDAPParser.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,224 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import static org.cauldron.sigil.model.common.Expressions.and;
+import static org.cauldron.sigil.model.common.Expressions.not;
+import static org.cauldron.sigil.model.common.Expressions.or;
+import static org.cauldron.sigil.model.common.Ops.APPROX;
+import static org.cauldron.sigil.model.common.Ops.EQ;
+import static org.cauldron.sigil.model.common.Ops.GE;
+import static org.cauldron.sigil.model.common.Ops.GT;
+import static org.cauldron.sigil.model.common.Ops.LE;
+import static org.cauldron.sigil.model.common.Ops.LT;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LDAPParser {
+
+    private static final LDAPParser parser = new LDAPParser();
+
+    public static LDAPExpr parseExpression(String strExpr) throws LDAPParseException {
+        return parser.parse(strExpr);
+    }
+
+    public static void main(String[] args) {
+        for (String arg : args) {
+            try {
+                System.out.println(parseExpression(arg));
+            }
+            catch (LDAPParseException e) {
+                System.out.println("Failed to parse " + arg);
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public LDAPExpr parse(String strExpr) throws LDAPParseException {
+
+        if (strExpr == null || strExpr.trim().length() == 0) {
+            return LDAPExpr.ACCEPT_ALL;
+        }
+
+        ParseState ps = new ParseState(strExpr);
+        LDAPExpr expr = parseExpr(ps);
+        ps.skipWhitespace();
+        if (!ps.isEndOfString()) {
+            error("expected end of expression ", ps);
+        }
+        return expr;
+    }
+
+    public LDAPExpr parseExpr(ParseState ps) throws LDAPParseException {
+        ps.skipWhitespace();
+        if (!(ps.peek() == '(')) {
+            error("expected (", ps);
+        }
+        ps.read();
+        LDAPExpr expr = null;
+        ps.skipWhitespace();
+        char ch = ps.peek();
+        switch (ch) {
+        case '&':
+            ps.readAndSkipWhiteSpace();
+            List<LDAPExpr> andList = new ArrayList<LDAPExpr>();
+            while (ps.peek() == '(') {
+                andList.add(parseExpr(ps));
+                ps.skipWhitespace();
+            }
+            LDAPExpr[] andArr = andList.toArray(new LDAPExpr[andList.size()]);
+            expr = and(andArr);
+            break;
+        case '|':
+            ps.readAndSkipWhiteSpace();
+            List<LDAPExpr> orList = new ArrayList<LDAPExpr>();
+            while (ps.peek() == '(') {
+                orList.add(parseExpr(ps));
+                ps.skipWhitespace();
+            }
+            LDAPExpr[] orArray = orList.toArray(new LDAPExpr[orList.size()]);
+            expr = or(orArray);
+            break;
+        case '!':
+            ps.readAndSkipWhiteSpace();
+            expr = not(parseExpr(ps));
+            break;
+        default:
+            if (isNameChar(ch)) {
+                expr = parseSimple(ps);
+            }
+            else {
+                error("unexpected character: '" + ch + "'", ps);
+            }
+        }
+        ps.skipWhitespace();
+        if (ps.peek() != ')') {
+            error("expected )", ps);
+        }
+        ps.read();
+        return expr;
+
+    }
+
+    void error(String message, ParseState ps) throws LDAPParseException {
+        throw new LDAPParseException(message, ps);
+    }
+
+    private SimpleTerm parseSimple(ParseState ps) throws LDAPParseException {
+        // read name
+        StringBuffer name = new StringBuffer(16);
+        for (char c = ps.peek(); !ps.isEndOfString() && isNameChar(c); c = ps.peek()) {
+            ps.read();
+            name.append(c);
+        }
+        ps.skipWhitespace();
+        Ops op = null;
+        // read op
+        if (ps.lookingAt("=")) {
+            op = EQ;
+            ps.skip(1);
+        }
+        else if (ps.lookingAt(">=")) {
+            op = GE;
+            ps.skip(2);
+        }
+        else if (ps.lookingAt("<=")) {
+            op = LE;
+            ps.skip(2);
+        }
+        else if (ps.lookingAt(">")) {
+            op = GT;
+            ps.skip(1);
+        }
+        else if (ps.lookingAt("<")) {
+            op = LT;
+            ps.skip(1);
+        }
+        else if (ps.lookingAt("-=")) {
+            op = APPROX;
+            ps.skip(2);
+        }
+        else if (ps.isEndOfString()) {
+            error("unexpected end of expression", ps);
+        }
+        else {
+            error("unexpected character: '" + ps.peek() + "'", ps);
+        }
+        ps.skipWhitespace();
+
+        boolean escaped = false;
+        StringBuffer value = new StringBuffer(16);
+
+        while (!ps.isEndOfString() && !Character.isWhitespace(ps.peek()) && !(ps.peek() == ')' && !escaped)) {
+
+            char ch = ps.peek();
+
+            if (ch == '\\') {
+                escaped = true;
+                ps.read();
+            }
+            else if (ch == '*') {
+                if (escaped) {
+                    value.append(ch);
+                    escaped = false;
+                }
+                else {
+                    value.append(SimpleTerm.WILDCARD);
+                }
+                ps.read();
+            }
+            else if (isLiteralValue(ch)) {
+                if (escaped) {
+                    error("incorrectly applied escape of '" + ch + "'", ps);
+                }
+                value.append(ps.read());
+            }
+            else if (isEscapedValue(ch)) {
+                if (!escaped) {
+                    error("missing escape for '" + ch + "'", ps);
+                }
+                value.append(ps.read());
+                escaped = false;
+            }
+            else {
+                error("unexpected character: '" + ps.peek() + "'", ps);
+            }
+        }
+        ps.skipWhitespace();
+
+        SimpleTerm expr = new SimpleTerm(name.toString(), op, value.toString());
+
+        return expr;
+    }
+
+    private boolean isNameChar(int ch) {
+        return !(Character.isWhitespace(ch) || (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') || (ch == '=')
+                || (ch == '~') || (ch == '*') || (ch == '\\'));
+    }
+
+    private boolean isLiteralValue(int ch) {
+        return !(Character.isWhitespace(ch) || (ch == '(') || (ch == ')') || (ch == '*'));
+    }
+
+    private boolean isEscapedValue(int ch) {
+        return (ch == '(') || (ch == ')') || (ch == '*');
+    }
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Not.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Not.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Not.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Not.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,87 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import java.util.Map;
+
+public class Not implements LDAPExpr {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+    private LDAPExpr[] children;
+
+    public static LDAPExpr apply(LDAPExpr e) {
+        if (e == null) {
+            throw new NullPointerException("cannot apply Not to a null expression");
+        }
+        if (e.equals(Expressions.T)) {
+            return Expressions.F;
+        }
+        if (e.equals(Expressions.F)) {
+            return Expressions.T;
+        }
+        return new Not(e);
+    }
+
+    private Not(LDAPExpr child) {
+        this.children = new LDAPExpr[] { child };
+    }
+
+    public boolean eval(Map<String, ?> map) {
+        return !children[0].eval(map);
+    }
+
+    public LDAPExpr getEx() {
+        return children[0];
+    }
+
+    public void visit(ExprVisitor v) {
+        v.visitNot(this);
+    }
+
+    public LDAPExpr[] getChildren() {
+        return children;
+    }
+
+    public void setChild(LDAPExpr child) {
+        this.children = new LDAPExpr[] { child };
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof Not) {
+            Not that = (Not) other;
+            return children[0].equals(that.children[0]);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer buf = new StringBuffer(256);
+        buf.append("(!");
+        buf.append(" ").append(children[0]).append(" ");
+        buf.append(")");
+        return buf.toString();
+    }
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Ops.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Ops.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Ops.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Ops.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,45 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+public enum Ops {
+    EQ, GE, LE, GT, LT, APPROX;
+
+    @Override
+    public String toString() {
+        switch (this) {
+        case EQ:
+            return "=";
+        case GE:
+            return ">=";
+        case LE:
+            return "<=";
+        case GT:
+            return ">";
+        case LT:
+            return "<";
+        case APPROX:
+            return "~=";
+        default:
+            return super.toString();
+        }
+    }
+
+}

Added: felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Or.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Or.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Or.java (added)
+++ felix/trunk/sigil/org.cauldron.bld.core/src/org/cauldron/sigil/model/common/Or.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,117 @@
+/*
+ * 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.cauldron.sigil.model.common;
+
+import java.util.Map;
+
+public class Or implements LDAPExpr {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+    private LDAPExpr[] children;
+
+    public static LDAPExpr apply(LDAPExpr... terms) {
+        if (terms == null) {
+            throw new NullPointerException("terms cannot be null");
+        }
+        else if (terms.length == 0) {
+            return Expressions.T;
+        }
+        else if (terms.length == 1) {
+            return terms[0];
+        }
+        LDAPExpr[] filtered = new LDAPExpr[terms.length];
+        int ctr = 0;
+        for (int i = 0; i < terms.length; i++) {
+            if (terms[i].equals(Expressions.T))
+                return Expressions.T;
+            if (terms[i].equals(Expressions.F))
+                continue;
+            filtered[ctr] = terms[i];
+            ctr++;
+        }
+        if (ctr == 0) {
+            return Expressions.F;
+        }
+        else if (ctr == 1) {
+            return filtered[0];
+        }
+        LDAPExpr[] orTerms = new LDAPExpr[ctr];
+        System.arraycopy(filtered, 0, orTerms, 0, ctr);
+
+        return new Or(orTerms);
+    }
+
+    private Or(LDAPExpr... children) {
+        this.children = children;
+    }
+
+    public boolean eval(Map<String, ?> map) {
+        for (int i = 0; i < children.length; i++) {
+            if (children[i].eval(map)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void visit(ExprVisitor v) {
+        v.visitOr(this);
+    }
+
+    public LDAPExpr[] getChildren() {
+        return children;
+    }
+
+    public void setChildren(LDAPExpr[] children) {
+        this.children = children;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof Or) {
+            Or that = (Or) other;
+            if (children.length != that.children.length) {
+                return false;
+            }
+            for (int i = 0; i < children.length; i++) {
+                if (children[i].equals(that.children[i])) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer buf = new StringBuffer(256);
+        buf.append("(|");
+        for (int i = 0; i < children.length; i++) {
+            buf.append(" ").append(children[i]).append(" ");
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+
+}