Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 55563 invoked from network); 17 Jul 2007 19:06:42 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 17 Jul 2007 19:06:42 -0000 Received: (qmail 72013 invoked by uid 500); 17 Jul 2007 19:06:41 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 71953 invoked by uid 500); 17 Jul 2007 19:06:41 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 71938 invoked by uid 99); 17 Jul 2007 19:06:41 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 17 Jul 2007 12:06:41 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 17 Jul 2007 12:06:38 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id C9E2E1A981A; Tue, 17 Jul 2007 12:06:15 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r557030 - in /cocoon/whiteboard/objectmodel/cocoon-expression-language: cocoon-expression-language-api/src/main/java/org/apache/cocoon/objectmodel/ cocoon-expression-language-impl/src/main/java/org/apache/cocoon/objectmodel/ cocoon-expressi... Date: Tue, 17 Jul 2007 19:06:15 -0000 To: cvs@cocoon.apache.org From: gkossakowski@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070717190615.C9E2E1A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: gkossakowski Date: Tue Jul 17 12:06:12 2007 New Revision: 557030 URL: http://svn.apache.org/viewvc?view=rev&rev=557030 Log: COCOON-2086: * changed constracts for ObjectModel interface, more in javadoc comments * dropped use of MultiValueMap because it did not conform to new ObjectModel interface * added test case testing new implementation of ObjectModelImpl Added: cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ObjectModelImplTestCase.java (with props) Modified: cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-api/src/main/java/org/apache/cocoon/objectmodel/ObjectModel.java cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/main/java/org/apache/cocoon/objectmodel/ObjectModelImpl.java Modified: cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-api/src/main/java/org/apache/cocoon/objectmodel/ObjectModel.java URL: http://svn.apache.org/viewvc/cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-api/src/main/java/org/apache/cocoon/objectmodel/ObjectModel.java?view=diff&rev=557030&r1=557029&r2=557030 ============================================================================== --- cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-api/src/main/java/org/apache/cocoon/objectmodel/ObjectModel.java (original) +++ cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-api/src/main/java/org/apache/cocoon/objectmodel/ObjectModel.java Tue Jul 17 12:06:12 2007 @@ -16,12 +16,16 @@ */ package org.apache.cocoon.objectmodel; +import java.util.Map; + import org.apache.commons.collections.MultiMap; /** - * ObjectModel is just a {@link MultiMap} with little more constrained and changed contracts. + * ObjectModel is a special {@link Map} that can have multiple values associated to the same key. If there is only one + * value associated with key then ObjectModel will behave exactly as {@link Map}. If there is more than one value associated with + * key then ObjectModel's methods will operate on {@link java.util.Collection Collections} associated with key. * - * One difference is that Collection for each key is compliant with LIFO list constracts. Another is about {@link #get(Object)} method. + * Another constrain is that {@link java.util.Collection} for each key is compliant with LIFO list constracts. */ public interface ObjectModel extends MultiMap { Modified: cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/main/java/org/apache/cocoon/objectmodel/ObjectModelImpl.java URL: http://svn.apache.org/viewvc/cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/main/java/org/apache/cocoon/objectmodel/ObjectModelImpl.java?view=diff&rev=557030&r1=557029&r2=557030 ============================================================================== --- cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/main/java/org/apache/cocoon/objectmodel/ObjectModelImpl.java (original) +++ cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/main/java/org/apache/cocoon/objectmodel/ObjectModelImpl.java Tue Jul 17 12:06:12 2007 @@ -16,39 +16,29 @@ */ package org.apache.cocoon.objectmodel; +import java.util.AbstractCollection; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.ListIterator; import org.apache.commons.collections.ArrayStack; -import org.apache.commons.collections.Factory; +import org.apache.commons.collections.iterators.IteratorChain; import org.apache.commons.collections.iterators.ReverseListIterator; -import org.apache.commons.collections.map.MultiValueMap; +import org.apache.commons.collections.iterators.SingletonIterator; +import org.apache.commons.collections.map.AbstractMapDecorator; /** * Prototype implementation of {@link ObjectModel} interface. It must be initialized manually for now. * */ -public class ObjectModelImpl extends MultiValueMap implements ObjectModel { +public class ObjectModelImpl extends AbstractMapDecorator implements ObjectModel { //FIXME: It seems that there is no easy way to reuse MuliValueMap - - public ObjectModelImpl() { - super(new HashMap(), new Factory() { - - public Object create() { - return new StackReversedIteration(); - } - - }); - } - public Object get(Object key) { - Collection collection = (Collection)super.get(key); - //if there is exactly one element in collection, return it instead of collection - return collection != null && (collection.size() == 1) ? collection.iterator().next() : collection; + public ObjectModelImpl() { + super(new HashMap()); } - + private static class StackReversedIteration extends ArrayStack { public Iterator iterator() { @@ -59,4 +49,115 @@ throw new UnsupportedOperationException(); } } + + public Object put(Object key, Object value) { + Object valuesForKey = getMap().get(key); + if (valuesForKey == null) { + super.put(key, value); + return value; + } + else if (valuesForKey instanceof StackReversedIteration) + return ((StackReversedIteration) valuesForKey).add(value) ? value : null; + else { + StackReversedIteration stack = new StackReversedIteration(); + stack.add(valuesForKey); + stack.add(value); + super.put(key, stack); + return value; + } + } + + public Object remove(Object key, Object item) { + Object valuesForKey = getMap().get(key); + if (valuesForKey == null) + return null; + else if (valuesForKey instanceof StackReversedIteration) { + StackReversedIteration stack = (StackReversedIteration)valuesForKey; + boolean changed = stack.remove(item); + if (stack.size() == 1) { + super.put(key, stack.pop()); + changed = true; + } + return changed ? item : null; + } + else + return super.remove(key); + } + + /** + * Gets the total size of the map by counting all the values. + * + * @return the total size of the map counting all values + */ + public int totalSize() { + int total = 0; + Collection values = getMap().values(); + for (Iterator it = values.iterator(); it.hasNext();) { + Object object = it.next(); + if (object instanceof StackReversedIteration) + total += ((Collection) object).size(); + else + total++; + } + return total; + } + + public Collection values() { + return new Values(); + } + + private class Values extends AbstractCollection { + public Iterator iterator() { + final IteratorChain chain = new IteratorChain(); + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + Object object = get(key); + if (object instanceof StackReversedIteration) + chain.addIterator(new ValuesIterator(key)); + else + //TODO: Implement removing + chain.addIterator(new SingletonIterator(object, false)); + } + return chain; + } + + public int size() { + return totalSize(); + } + + public void clear() { + ObjectModelImpl.this.clear(); + } + } + + /** + * Inner class that provides the values iterator. + */ + private class ValuesIterator implements Iterator { + private final Object key; + private final Collection values; + private final Iterator iterator; + + public ValuesIterator(Object key) { + this.key = key; + this.values = (Collection)getMap().get(key); + this.iterator = values.iterator(); + } + + public void remove() { + iterator.remove(); + if (values.isEmpty()) { + ObjectModelImpl.this.remove(key); + } + } + + public boolean hasNext() { + return iterator.hasNext(); + } + + public Object next() { + return iterator.next(); + } + } + } Added: cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ObjectModelImplTestCase.java URL: http://svn.apache.org/viewvc/cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ObjectModelImplTestCase.java?view=auto&rev=557030 ============================================================================== --- cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ObjectModelImplTestCase.java (added) +++ cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ObjectModelImplTestCase.java Tue Jul 17 12:06:12 2007 @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.objectmodel; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.TestCase; + +public class ObjectModelImplTestCase extends TestCase { + + public void testMap() { + ObjectModel objectModel = new ObjectModelImpl(); + + objectModel.put("foo1", "bar1"); + assertEquals("bar2", objectModel.put("foo2", "bar2")); + assertEquals(true, objectModel.containsKey("foo1")); + assertEquals("bar2", objectModel.get("foo2")); + + objectModel.remove("foo1"); + assertEquals(null, objectModel.get("foo1")); + } + + public void testMultiValue() { + ObjectModel objectModel = new ObjectModelImpl(); + + objectModel.put("foo", "bar1"); + objectModel.put("foo", "bar2"); + assertEquals(2, ((Collection)objectModel.get("foo")).size()); + + objectModel.remove("foo", "bar2"); + assertEquals("bar1", objectModel.get("foo")); + + objectModel.remove("foo", "bar1"); + assertEquals(null, objectModel.get("foo")); + } + + public void testValues() { + ObjectModel objectModel = new ObjectModelImpl(); + + objectModel.put("foo", "bar1"); + Collection values = objectModel.values(); + assertEquals(true, values.contains("bar1")); + + objectModel.put("foo", "bar2"); + values = objectModel.values(); + assertEquals(true, values.contains("bar1")); + assertEquals(true, values.contains("bar2")); + + objectModel.remove("foo", "bar1"); + values = objectModel.values(); + assertEquals(false, values.contains("bar1")); + } + +} Propchange: cocoon/whiteboard/objectmodel/cocoon-expression-language/cocoon-expression-language-impl/src/test/java/org/apache/cocoon/objectmodel/ObjectModelImplTestCase.java ------------------------------------------------------------------------------ svn:eol-style = native