cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dand...@apache.org
Subject svn commit: r481980 - in /incubator/cxf/trunk: distribution/src/main/release/ rt/bindings/http/src/main/java/org/apache/cxf/binding/http/ rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ rt/bindings/http/src/test/java/org/apache/cxf...
Date Sun, 03 Dec 2006 23:06:35 GMT
Author: dandiep
Date: Sun Dec  3 15:06:34 2006
New Revision: 481980

URL: http://svn.apache.org/viewvc?view=rev&rev=481980
Log:
o Separate out the annotation logic from HttpBindingInfoFactory to
  allow many different strategies of mapping services to HTTP URIs.
  This is now encapsulated in the ResourceStrategy interface.
o Add a convention based strategy that looks at your method names
  and parameters and determines the best way to map your service to 
  URIs. It is able to create the same HTTP service and URIs that the
  annotations did in my original CustomerService!
o Add Inflector code to turn "customer" into "customers" for the 
  convention based strategy. This is based on the Ruby On Rails code
  that does the same thing. I've included their MIT license and
  also put a notice in the NOTICE file.

Added:
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
  (with props)
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
  (with props)
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
  (with props)
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
  (with props)
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
  (with props)
    incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
  (with props)
Modified:
    incubator/cxf/trunk/distribution/src/main/release/NOTICE
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpBindingInfoFactoryBean.java
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpConstants.java
    incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/wrapped/WrappedServiceTest.java

Modified: incubator/cxf/trunk/distribution/src/main/release/NOTICE
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/distribution/src/main/release/NOTICE?view=diff&rev=481980&r1=481979&r2=481980
==============================================================================
--- incubator/cxf/trunk/distribution/src/main/release/NOTICE (original)
+++ incubator/cxf/trunk/distribution/src/main/release/NOTICE Sun Dec  3 15:06:34 2006
@@ -48,7 +48,7 @@
    This product also includes software developed by Mort Bay Consulting
    Pty (http://jetty.mortbay.org)
 
-   This product also includes software developed by Codehause
+   This product also includes software developed by Codehaus
    (http://woodstox.codehaus.org/)
 
    This product also includes MTOSI wsdl and schemas developed to TeleManagement
@@ -70,6 +70,9 @@
    Java classes (source and binary) under org.apache.cxf.jaxws.javaee
    are generated from schema available here:
    (http://java.sun.com/xml/ns/javaee/javaee_5.xsd)
+
+   This Product also includes software developed by David Heinemeier Hansson.
+   (http://dev.rubyonrails.org/browser/trunk/activesupport/lib/active_support/inflections.rb)
 
    Additional copyright notices and license terms applicable are
    present in the licenses directory of this distribution.

Modified: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpBindingInfoFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpBindingInfoFactoryBean.java?view=diff&rev=481980&r1=481979&r2=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpBindingInfoFactoryBean.java
(original)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpBindingInfoFactoryBean.java
Sun Dec  3 15:06:34 2006
@@ -19,9 +19,14 @@
 package org.apache.cxf.binding.http;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.xml.namespace.QName;
 
+import org.apache.cxf.binding.http.strategy.ConventionStrategy;
+import org.apache.cxf.binding.http.strategy.JRAStrategy;
+import org.apache.cxf.binding.http.strategy.ResourceStrategy;
 import org.apache.cxf.service.Service;
 import org.apache.cxf.service.factory.AbstractBindingInfoFactoryBean;
 import org.apache.cxf.service.factory.MethodDispatcher;
@@ -29,18 +34,21 @@
 import org.apache.cxf.service.model.BindingInfo;
 import org.apache.cxf.service.model.BindingOperationInfo;
 import org.apache.cxf.service.model.OperationInfo;
-import org.codehaus.jra.Delete;
-import org.codehaus.jra.Get;
-import org.codehaus.jra.HttpResource;
-import org.codehaus.jra.Post;
-import org.codehaus.jra.Put;
 
 public class HttpBindingInfoFactoryBean extends AbstractBindingInfoFactoryBean {
-
-    private URIMapper mapper = new URIMapper();
+    private List<ResourceStrategy> strategies = new ArrayList<ResourceStrategy>();
     
+    public HttpBindingInfoFactoryBean() {
+        super();
+        
+        strategies.add(new JRAStrategy());
+        strategies.add(new ConventionStrategy());
+    }
+
     @Override
     public BindingInfo create() {
+        URIMapper mapper = new URIMapper();
+        
         BindingInfo info = new BindingInfo(getServiceInfo(), 
                                            HttpBindingFactory.HTTP_BINDING_ID);
         info.setName(new QName(getServiceInfo().getName().getNamespaceURI(), 
@@ -57,29 +65,26 @@
             
             Method m = md.getMethod(bop);
             
-            HttpResource r = m.getAnnotation(HttpResource.class);
-            if (r == null) {
-                continue;
-            }
-            
-            String verb;
-            if (m.isAnnotationPresent(Get.class)) {
-                verb = "GET";
-            } else if (m.isAnnotationPresent(Post.class)) {
-                verb = "POST";
-            } else if (m.isAnnotationPresent(Put.class)) {
-                verb = "PUT";
-            } else if (m.isAnnotationPresent(Delete.class)) {
-                verb = "DELETE";
-            } else {
-                // todo: use the method name to determine the verb
-                verb = "GET";
+            // attempt to map the method to a resource using different strategies
+            for (ResourceStrategy s : strategies) {
+                // Try different ones until we find one that succeeds
+                if (s.map(bop, m, mapper)) {
+                    break;
+                }
             }
-            
-            mapper.bind(bop, r.location(), verb);
         }
         
         service.put(URIMapper.class.getName(), mapper);
         return info;
     }
+
+    public List<ResourceStrategy> getStrategies() {
+        return strategies;
+    }
+
+    public void setStrategies(List<ResourceStrategy> strategies) {
+        this.strategies = strategies;
+    }
+
+    
 }

Modified: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpConstants.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpConstants.java?view=diff&rev=481980&r1=481979&r2=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpConstants.java
(original)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/HttpConstants.java
Sun Dec  3 15:06:34 2006
@@ -21,5 +21,8 @@
 public class HttpConstants {
 
     public static final String CONTENT_TYPE = "Content-Type";
-
+    public static final String POST = "POST";
+    public static final String PUT = "PUT";
+    public static final String DELETE = "DELETE";
+    public static final String GET = "GET";
 }

Added: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java?view=auto&rev=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
(added)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
Sun Dec  3 15:06:34 2006
@@ -0,0 +1,162 @@
+/**
+ * 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.cxf.binding.http.strategy;
+
+import java.lang.reflect.Method;
+import java.util.logging.Logger;
+
+import org.apache.cxf.binding.http.URIMapper;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.apache.cxf.service.model.MessagePartInfo;
+
+import static org.apache.cxf.binding.http.HttpConstants.DELETE;
+import static org.apache.cxf.binding.http.HttpConstants.GET;
+import static org.apache.cxf.binding.http.HttpConstants.POST;
+import static org.apache.cxf.binding.http.HttpConstants.PUT;
+
+/**
+ * <p>
+ * Maps a BindingOperation to a URI/combination using the following rules:
+ * </p>
+ * <p>
+ * <b>GET Operations:</b> If the operation name starts with "get" and it has
+ * no parameters, it is assumed it is a get for a collection of objects. The
+ * noun after the "get" is turned into the resource name. Example: "getCustomers"
+ * is turned into "/customers". 
+ * </p>
+ * <p>
+ * If the operation name starts with "get" and it takes parameters, it is taken
+ * to be a get for a singular noun. In this case the noun is pluralized, and the
+ * resource name is the pluralized noun and any additional parameters the operation
+ * takes. For the case of the operation which has a signature of 
+ * "Customer getCustomer(String id)" the resource would become "/customers/{id}". 
+ * </p>
+ * 
+ * <p>
+ * <b>POST Operations:</b> If the operation name starts with "add" or "create"
+ * it is turned into a POST operation. In this case noun after add/create is 
+ * pluralized and turned into the resource name. Example: "addCustomer(Customer)"
+ * is truned into "/customers".
+ * </p>
+ * <p>
+ * <b>PUT Operations:</b> If the operation name starts with "update"
+ * it is turned into a PUT operation. In this case the resource name is the
+ * pluralized noun after "update" and any additional XML schema primitive
+ * parameters the operation takes.  Example: "updateCustomer(String id, Customer c)"
+ * becomes "/customers/{id}". The customer object does NOT become part of the 
+ * resource name because it doesn't map to an XML schema primitive type such as
+ * xsd:int, xsd:string, etc.
+ * </p>
+ * <b>DELETE Operations:</b> Delete operations follow the same rules as PUT 
+ * operations, except the operation name must start with either "delete" or
+ * "remove". Example: "deleteCustomer(String id,)" becomes "/customers/{id}".
+ * </p>
+ *
+ */
+public class ConventionStrategy implements ResourceStrategy {
+    private static final Logger LOG = Logger.getLogger(ConventionStrategy.class.getName());
+    private Inflector inflector = new EnglishInflector();
+
+    public boolean map(BindingOperationInfo bop, Method m, URIMapper mapper) {
+        String name = m.getName();
+        String verb;
+        String noun;
+        String resource;
+
+        // find the most appropriate binding operation
+        BindingOperationInfo bopWithParts = bop.isUnwrappedCapable() ? bop.getUnwrappedOperation()
: bop;
+        boolean pluralize = bopWithParts.getInput().getMessageParts().size() > 0;
+
+        if (name.startsWith("get")) {
+            verb = GET;
+            noun = extractNoun(name, 3, pluralize);
+            resource = createResourceName(noun, bopWithParts);
+        } else if (name.startsWith("add")) {
+            verb = POST;
+            noun = extractNoun(name, 3, pluralize);
+            resource = noun;
+        } else if (name.startsWith("create")) {
+            verb = POST;
+            noun = extractNoun(name, 5, pluralize);
+            resource = noun;
+        } else if (name.startsWith("update")) {
+            verb = PUT;
+            noun = extractNoun(name, 6, pluralize);
+            resource = createResourceName(noun, bopWithParts);
+        } else if (name.startsWith("remove") || name.startsWith("delete")) {
+            verb = DELETE;
+            noun = extractNoun(name, 6, pluralize);
+            resource = createResourceName(noun, bopWithParts);
+        } else {
+            verb = POST;
+            noun = name;
+            resource = noun;
+        }
+
+        resource = '/' + resource;
+
+        LOG.info("Mapping method " + name + " to resource " + resource + " and verb " + verb);
+
+        mapper.bind(bop, resource, verb);
+
+        return true;
+    }
+
+    private String createResourceName(String noun, BindingOperationInfo bopWithParts) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(noun);
+        for (MessagePartInfo part : bopWithParts.getInput().getMessageParts()) {
+            if (isXSDPrimitive(part)) {
+                builder.append("/{").append(part.getName().getLocalPart()).append("}");
+            }
+        }
+        return builder.toString();
+    }
+
+    private boolean isXSDPrimitive(MessagePartInfo part) {
+        String xsdNs = "http://www.w3.org/2001/XMLSchema";
+        if (!part.isElement() 
+            && part.getTypeQName().getNamespaceURI().equals(xsdNs)) {
+            return true;
+        }
+        
+        // TODO: introspect xml schema object to see if the <xsd:element> is a simpleType
+        // restriction
+        return false;
+    }
+
+    private String extractNoun(String name, int n, boolean pluralize) {
+        name = name.substring(n, n + 1).toLowerCase() + name.substring(n + 1);
+
+        if (pluralize) {
+            name = inflector.pluralize(name);
+        }
+
+        return name;
+    }
+
+    public Inflector getInflector() {
+        return inflector;
+    }
+
+    public void setInflector(Inflector inflector) {
+        this.inflector = inflector;
+    }
+
+}

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ConventionStrategy.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java?view=auto&rev=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
(added)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
Sun Dec  3 15:06:34 2006
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+/**
+ * Copyright (c) 2005-2006 David Heinemeier Hansson
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.apache.cxf.binding.http.strategy;
+
+/**
+ * Rules for English inflection.
+ * <p>
+ * Notice: Some portions of this class where ported from Ruby's ActiveSupport
+ * library which are Copyright (c) 2005-2006 David Heinemeier Hansson and
+ * under the MIT license.
+ */
+public class EnglishInflector extends Inflector {
+    
+    public EnglishInflector() {
+        addPlural("$", "s");
+        addPlural("s$", "$1s");
+        addPlural("(ax|test)is$", "$1es");
+        addPlural("(octop|vir)us$", "$1i");
+        addPlural("(alias|status)$", "$1es");
+        addPlural("(bu)s$", "$1ses");
+        addPlural("(buffal|tomat)o$", "$1oes");
+        addPlural("([ti])um$", "$1a");
+        addPlural("sis$", "ses");
+        addPlural("(?:([^f])fe|([lr])f)$", "$1\2ves");
+        addPlural("(hive)$", "$1s");
+        addPlural("([^aeiouy]|qu)y$", "$1ies");
+        addPlural("(x|ch|ss|sh)$", "$1es");
+        addPlural("(matr|vert|ind)ix|ex$", "$1ices");
+        addPlural("([m|l])ouse$", "$1ice");
+        addPlural("^(ox)$", "$1en");
+        addPlural("(quiz)$", "$1zes");
+
+        addSingular("s$", "");
+        addSingular("(n)ews$", "$1ews");
+        addSingular("([ti])a$", "$1um");
+        addSingular("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1\2sis");
+        addSingular("(^analy)ses$", "$1sis");
+        addSingular("([^f])ves$", "$1fe");
+        addSingular("(hive)s$", "$1");
+        addSingular("(tive)s$", "$1");
+        addSingular("([lr])ves$", "$1f");
+        addSingular("([^aeiouy]|qu)ies$", "$1y");
+        addSingular("(s)eries$", "$1eries");
+        addSingular("(m)ovies$", "$1ovie");
+        addSingular("(x|ch|ss|sh)es$", "$1");
+        addSingular("([m|l])ice$", "$1ouse");
+        addSingular("(bus)es$", "$1");
+        addSingular("(o)es$", "$1");
+        addSingular("(shoe)s$", "$1");
+        addSingular("(cris|ax|test)es$", "$1is");
+        addSingular("(octop|vir)i$", "$1us");
+        addSingular("(alias|status)es$", "$1");
+        addSingular("^(ox)en", "$1");
+        addSingular("(vert|ind)ices$", "$1ex");
+        addSingular("(matr)ices$", "$1ix");
+        addSingular("(quiz)zes$", "$1");
+
+        addIrregular("person", "people");
+        addIrregular("man", "men");
+        addIrregular("child", "children");
+        addIrregular("sex", "sexes");
+        addIrregular("move", "moves");
+
+        addUncountable(new String[] {"equipment", "information", "rice", 
+                                     "money", "species", "series", "fish", "sheep"});
+    }
+}

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/EnglishInflector.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java?view=auto&rev=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
(added)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
Sun Dec  3 15:06:34 2006
@@ -0,0 +1,115 @@
+/**
+ * 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.cxf.binding.http.strategy;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Inflector {
+    
+    private List<String> uncountable = new ArrayList<String>();
+    private List<Rule> singular = new ArrayList<Rule>();
+    private List<Rule> plural = new ArrayList<Rule>();
+    private Map<String, String> irregular = new HashMap<String, String>();
+
+    public String singularlize(String orig) {
+        if (uncountable.contains(orig)) {
+            return orig;
+        } 
+        
+        for (Map.Entry<String, String> entry : irregular.entrySet()) {
+            if (entry.getValue().equals(orig)) {
+                return entry.getKey();
+            }
+        }
+        
+        for (Rule r : singular) {
+            Matcher m = r.getRegex().matcher(orig);
+            if (m.find()) {
+                return m.replaceAll(r.getReplacement());
+            }
+        }
+       
+        return orig;
+    }
+    
+    public String pluralize(String orig) {
+        if (uncountable.contains(orig)) {
+            return orig;
+        } 
+        
+        String irr = irregular.get(orig);
+        if (irr != null) {
+            return irr;
+        }
+        
+        for (Rule r : plural) {
+            Matcher m = r.getRegex().matcher(orig);
+            //System.out.println(m.pattern().pattern());
+            if (m.find()) {
+                //System.out.println("!!!found match!!!");
+                return m.replaceAll(r.getReplacement());
+            }
+        }
+       
+        return orig;
+    }
+    
+    public void addPlural(String regex, String replacement) {
+        plural.add(0, new Rule(regex, replacement));
+    }
+    
+    public void addSingular(String regex, String replacement) {
+        singular.add(0, new Rule(regex, replacement));
+    }
+    
+    public void addIrregular(String orig, String replacement) {
+        irregular.put(orig, replacement);
+    }
+    
+    public void addUncountable(String[] words) {
+        uncountable.addAll(Arrays.asList(words));
+    }
+    
+    public void addUncountable(String word) {
+        uncountable.add(word);
+    }
+    
+    static class Rule {
+        private Pattern regex;
+        private String replacement;
+        
+        public Rule(String regex, String replacement) {
+            this.regex = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+            this.replacement = replacement;
+        }
+        
+        public Pattern getRegex() {
+            return regex;
+        }
+        public String getReplacement() {
+            return replacement;
+        }
+    }
+}

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/Inflector.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java?view=auto&rev=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
(added)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
Sun Dec  3 15:06:34 2006
@@ -0,0 +1,66 @@
+/**
+ * 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.cxf.binding.http.strategy;
+
+import java.lang.reflect.Method;
+
+import org.apache.cxf.binding.http.URIMapper;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.codehaus.jra.Delete;
+import org.codehaus.jra.Get;
+import org.codehaus.jra.HttpResource;
+import org.codehaus.jra.Post;
+import org.codehaus.jra.Put;
+
+import static org.apache.cxf.binding.http.HttpConstants.DELETE;
+import static org.apache.cxf.binding.http.HttpConstants.GET;
+import static org.apache.cxf.binding.http.HttpConstants.POST;
+import static org.apache.cxf.binding.http.HttpConstants.PUT;
+
+/**
+ * A strategy to map BindingOperationInfos to URI/Verb combos utilizing the
+ * <a href="http://jra.codehaus.org">Java Rest Annotations</a>.
+ */
+public class JRAStrategy implements ResourceStrategy {
+
+    public boolean map(BindingOperationInfo bop, Method m, URIMapper mapper) {
+        HttpResource r = m.getAnnotation(HttpResource.class);
+        if (r == null) {
+            return false;
+        }
+        
+        String verb;
+        if (m.isAnnotationPresent(Get.class)) {
+            verb = GET;
+        } else if (m.isAnnotationPresent(Post.class)) {
+            verb = POST;
+        } else if (m.isAnnotationPresent(Put.class)) {
+            verb = PUT;
+        } else if (m.isAnnotationPresent(Delete.class)) {
+            verb = DELETE;
+        } else {
+            verb = POST;
+        }
+        
+        mapper.bind(bop, r.location(), verb);
+        
+        return true;
+    }
+    
+}

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/JRAStrategy.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java?view=auto&rev=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
(added)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
Sun Dec  3 15:06:34 2006
@@ -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.apache.cxf.binding.http.strategy;
+
+import java.lang.reflect.Method;
+
+import org.apache.cxf.binding.http.URIMapper;
+import org.apache.cxf.service.model.BindingOperationInfo;
+
+/**
+ * A ResourceStrategy represents a method of mapping an Operation to a
+ * URI/Verb combination. 
+ */
+public interface ResourceStrategy {
+
+    boolean map(BindingOperationInfo bop, Method m, URIMapper mapper);
+
+}

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/strategy/ResourceStrategy.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java?view=auto&rev=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
(added)
+++ incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
Sun Dec  3 15:06:34 2006
@@ -0,0 +1,63 @@
+/**
+ * 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.
+ */
+/**
+ * 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.cxf.binding.http;
+
+import junit.framework.TestCase;
+
+import org.apache.cxf.binding.http.strategy.EnglishInflector;
+import org.apache.cxf.binding.http.strategy.Inflector;
+
+public class InflectorTest extends TestCase {
+    public void testPluralization() {
+        Inflector i = new EnglishInflector();
+        assertEquals("quizzes", i.pluralize("quiz"));
+        assertEquals("QUIZzes", i.pluralize("QUIZ"));
+        assertEquals("matrices", i.pluralize("matrix"));
+        assertEquals("people", i.pluralize("person"));
+        assertEquals("kids", i.pluralize("kid"));
+        assertEquals("bashes", i.pluralize("bash"));
+    }
+    
+    public void testSingularization() {
+        Inflector i = new EnglishInflector();
+        assertEquals("matrix", i.singularlize("matrices"));
+        assertEquals("quiz", i.singularlize("quizzes"));
+        assertEquals("person", i.singularlize("people"));
+        assertEquals("kid", i.singularlize("kids"));
+        assertEquals("bash", i.singularlize("bashes"));
+    }
+}

Propchange: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/InflectorTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/wrapped/WrappedServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/wrapped/WrappedServiceTest.java?view=diff&rev=481980&r1=481979&r2=481980
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/wrapped/WrappedServiceTest.java
(original)
+++ incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/wrapped/WrappedServiceTest.java
Sun Dec  3 15:06:34 2006
@@ -28,12 +28,26 @@
 import org.apache.cxf.binding.http.HttpBindingFactory;
 import org.apache.cxf.binding.http.HttpBindingInfoFactoryBean;
 import org.apache.cxf.binding.http.URIMapper;
+import org.apache.cxf.binding.http.strategy.ConventionStrategy;
 import org.apache.cxf.endpoint.ServerImpl;
 import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
 import org.apache.cxf.service.model.BindingOperationInfo;
 
 public class WrappedServiceTest extends AbstractRestTest {
-    public void testCreation() throws Exception {
+    
+    public void testConvention() throws Exception {
+        HttpBindingInfoFactoryBean hbif = new HttpBindingInfoFactoryBean();
+        hbif.getStrategies().clear();
+        hbif.getStrategies().add(new ConventionStrategy());
+        
+        testService(hbif);
+    }
+    
+    public void testJRA() throws Exception {
+        testService(new HttpBindingInfoFactoryBean());
+    }
+
+    public void testService(HttpBindingInfoFactoryBean httpFactory) throws Exception {
         BindingFactoryManager bfm = getBus().getExtension(BindingFactoryManager.class);
         bfm.registerBindingFactory(HttpBindingFactory.HTTP_BINDING_ID, new HttpBindingFactory());
         
@@ -41,7 +55,7 @@
         sf.setBus(getBus());
         sf.setServiceClass(CustomerService.class);
         sf.getServiceFactory().setWrapped(true);
-        sf.setBindingFactory(new HttpBindingInfoFactoryBean());
+        sf.setBindingFactory(httpFactory);
         sf.setAddress("http://localhost:9001/");
 
         Map<String, Object> props = new HashMap<String, Object>();



Mime
View raw message