You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/11/28 16:03:03 UTC

git commit: ISIS-612: URL as value type; returning URL opens in Wicket

Updated Branches:
  refs/heads/master 5e5b07c46 -> 8b14424c6


ISIS-612: URL as value type; returning URL opens in Wicket


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/8b14424c
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/8b14424c
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/8b14424c

Branch: refs/heads/master
Commit: 8b14424c693b247f2f87a290693226ab6189d59b
Parents: 5e5b07c
Author: Dan Haywood <da...@apache.org>
Authored: Thu Nov 28 15:02:47 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Thu Nov 28 15:02:47 2013 +0000

----------------------------------------------------------------------
 .../additionallinks/EntityActionUtil.java       |   2 +-
 .../cssmenu/AppActionsCssMenuLinkFactory.java   |   6 +-
 .../entity/EntityActionLinkFactory.java         |   9 +-
 .../components/value/StandaloneValuePanel.java  |   8 ++
 .../widgets/cssmenu/CssMenuLinkFactory.java     |  16 +++
 .../json/LayoutMetadataReaderFromJson.java      |   2 +-
 .../metamodel/spec/feature/ObjectAction.java    |  50 ++++++-
 .../metamodel/spec/feature/ObjectActions.java   |  49 +++----
 .../facets/value/url/URLValueFacet.java         |  30 +++++
 .../value/url/URLValueSemanticsProvider.java    | 132 +++++++++++++++++++
 .../value/url/URLValueTypeFacetFactory.java     |  42 ++++++
 .../dflt/ProgrammingModelFacetsJava5.java       |   2 +
 .../dom/src/main/java/dom/todo/ToDoItems.java   |   3 +
 .../webapp/prototyping/DeveloperUtilities.java  |   1 +
 .../prototyping/ExternalLinksService.java       |  44 +++++++
 .../src/main/webapp/WEB-INF/isis.properties     |   1 +
 16 files changed, 357 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
index dac7df2..846c258 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
@@ -62,7 +62,7 @@ public final class EntityActionUtil {
         
         @SuppressWarnings("unchecked")
         final List<ObjectAction> userActions = adapterSpec.getObjectActions(ActionType.USER, Contributed.INCLUDED,
-                Filters.and(ObjectActions.memberOrderOf(association), EntityActionUtil.dynamicallyVisibleFor(adapter)));
+                Filters.and(ObjectAction.Filters.memberOrderOf(association), EntityActionUtil.dynamicallyVisibleFor(adapter)));
         Collections.sort(userActions, new Comparator<ObjectAction>() {
 
             @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
index 1b15709..7ba4c8e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
@@ -26,7 +26,6 @@ import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
@@ -48,7 +47,10 @@ class AppActionsCssMenuLinkFactory implements CssMenuLinkFactory {
         final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ACTION);
 
         final AbstractLink link = Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);
-        final String actionLabel = ObjectActions.nameFor(action);
+        final String actionLabel = ObjectAction.Utils.nameFor(action);
+        
+        // special case handling if this action is returning a URL
+        Util.addTargetBlankIfActionReturnsUrl(link, action);
 
         final boolean blobOrClob = CssMenuItem.returnsBlobOrClob(action);
         final boolean prototype = CssMenuItem.isExplorationOrPrototype(action);

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
index 46d01fe..0844c77 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
@@ -21,8 +21,10 @@ package org.apache.isis.viewer.wicket.ui.components.entity;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.Page;
+import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.model.Model;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.isis.applib.annotation.ActionSemantics;
@@ -31,6 +33,7 @@ import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
 import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -55,6 +58,7 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
 
     private static final long serialVersionUID = 1L;
 
+    @SuppressWarnings("unused")
     private final EntityModel entityModel;
 
     public EntityActionLinkFactory(final EntityModel entityModel) {
@@ -67,7 +71,7 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
 
         final AbstractLink link = createLink(adapterMemento, action, linkId, adapter);
         //action
-        final String label = ObjectActions.nameFor(action);
+        final String label = ObjectAction.Utils.nameFor(action);
 
         // check visibility and whether enabled
         final AuthenticationSession session = getAuthenticationSession();
@@ -83,6 +87,9 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
             link.setEnabled(false);
         }
 
+        // special case handling if this action is returning a URL
+        Util.addTargetBlankIfActionReturnsUrl(link, action);
+
         final boolean blobOrClob = CssMenuItem.returnsBlobOrClob(action);
         final boolean prototype = CssMenuItem.isExplorationOrPrototype(action);
         final String actionIdentifier = CssMenuItem.actionIdentifierFor(action);

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/value/StandaloneValuePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/value/StandaloneValuePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/value/StandaloneValuePanel.java
index a0748de..b8281a7 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/value/StandaloneValuePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/value/StandaloneValuePanel.java
@@ -20,8 +20,10 @@
 package org.apache.isis.viewer.wicket.ui.components.value;
 
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.handler.resource.ResourceRequestHandler;
 import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
+import org.apache.wicket.request.http.handler.RedirectRequestHandler;
 import org.apache.wicket.request.resource.ByteArrayResource;
 import org.apache.wicket.request.resource.ContentDisposition;
 import org.apache.wicket.util.resource.StringResourceStream;
@@ -61,6 +63,12 @@ public class StandaloneValuePanel extends PanelAbstract<ValueModel> {
                     new ResourceRequestHandler(new ByteArrayResource(blob.getMimeType().toString(), blob.getBytes(), blob.getName()), null);
             getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
             label = "Downloading: " + blob.getName();
+        } else if(value instanceof java.net.URL) {
+            java.net.URL url = (java.net.URL) value;
+            label = "Downloading: " + objectAdapter.titleString(null);
+            IRequestHandler handler = 
+                    new RedirectRequestHandler(url.toString());
+            getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
         } else {
             label = objectAdapter.titleString(null);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
index 64c9791..92fa9d3 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
@@ -21,6 +21,11 @@ package org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu;
 
 import java.io.Serializable;
 
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.model.Model;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
@@ -32,4 +37,15 @@ public interface CssMenuLinkFactory extends Serializable {
 
     LinkAndLabel newLink(ObjectAdapterMemento adapter, ObjectAction noAction, String linkId);
 
+    public static class Util {
+        private Util() {}
+        public static void addTargetBlankIfActionReturnsUrl(AbstractLink link, ObjectAction action) {
+            final ObjectSpecification returnType = action.getReturnType();
+            if(returnType != null && "java.net.URL".equals(returnType.getFullIdentifier())) {
+                link.add(new AttributeAppender("target", Model.of("_blank")));
+            }
+        }
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
index c51b4bf..6b5b94f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
@@ -447,7 +447,7 @@ public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
         }
 
         final List<ObjectAction> actions = objectSpec.getObjectActions(
-                ActionType.USER, Contributed.INCLUDED, ObjectActions.memberOrderOf(assoc));
+                ActionType.USER, Contributed.INCLUDED, ObjectAction.Filters.memberOrderOf(assoc));
         if(!actions.isEmpty()) {
             memberRepr.actions = Maps.newLinkedHashMap();
             

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
index c3227a3..b056e92 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
@@ -21,6 +21,8 @@ package org.apache.isis.core.metamodel.spec.feature;
 
 import java.util.List;
 
+import com.google.common.base.Strings;
+
 import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.When;
 import org.apache.isis.applib.annotation.Where;
@@ -33,6 +35,8 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetFilters;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.hide.HiddenFacet;
+import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
+import org.apache.isis.core.metamodel.facets.named.NamedFacet;
 import org.apache.isis.core.metamodel.interactions.AccessContext;
 import org.apache.isis.core.metamodel.interactions.ActionInvocationContext;
 import org.apache.isis.core.metamodel.interactions.ValidatingInteractionAdvisor;
@@ -175,10 +179,34 @@ public interface ObjectAction extends ObjectMember {
 
 
     // //////////////////////////////////////////////////////
+    // Utils
+    // //////////////////////////////////////////////////////
+
+    public static final class Utils {
+
+        private Utils() {
+        }
+
+        public static String nameFor(final ObjectAction noAction) {
+            final String actionName = noAction.getName();
+            if (actionName != null) {
+                return actionName;
+            }
+            final NamedFacet namedFacet = noAction.getFacet(NamedFacet.class);
+            if (namedFacet != null) {
+                return namedFacet.value();
+            }
+            return "(no name)";
+        }
+    }
+
+
+    // //////////////////////////////////////////////////////
     // Filters
     // //////////////////////////////////////////////////////
 
-    public static class Filters {
+    
+    public static final class Filters {
         
         private Filters(){}
         
@@ -236,5 +264,25 @@ public interface ObjectAction extends ObjectMember {
                 }};
         }
         
+        public static Filter<ObjectAction> memberOrderOf(ObjectAssociation association) {
+            final String assocName = association.getName();
+            final String assocId = association.getId();
+            return new Filter<ObjectAction>() {
+        
+                @Override
+                public boolean accept(ObjectAction t) {
+                    final MemberOrderFacet memberOrderFacet = t.getFacet(MemberOrderFacet.class);
+                    if(memberOrderFacet == null) {
+                        return false; 
+                    }
+                    final String memberOrderName = memberOrderFacet.name();
+                    if(Strings.isNullOrEmpty(memberOrderName)) {
+                        return false;
+                    }
+                    return memberOrderName.equalsIgnoreCase(assocName) || memberOrderName.equalsIgnoreCase(assocId);
+                }
+            };
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActions.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActions.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActions.java
index 2889e57..c167879 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActions.java
@@ -19,50 +19,31 @@
 
 package org.apache.isis.core.metamodel.spec.feature;
 
-import java.util.List;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-
 import org.apache.isis.applib.filter.Filter;
-import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
-import org.apache.isis.core.metamodel.facets.named.NamedFacet;
 
+/**
+ * @deprecated
+ */
+@Deprecated
 public final class ObjectActions {
 
     private ObjectActions() {
     }
 
-    public static String nameFor(final ObjectAction noAction) {
-        final String actionName = noAction.getName();
-        if (actionName != null) {
-            return actionName;
-        }
-        final NamedFacet namedFacet = noAction.getFacet(NamedFacet.class);
-        if (namedFacet != null) {
-            return namedFacet.value();
-        }
-        return "(no name)";
+    /**
+     * @deprecated - use {@link ObjectAction.Utils#nameFor(ObjectAction)}
+     */
+    @Deprecated
+    public static String nameFor(final ObjectAction action) {
+        return ObjectAction.Utils.nameFor(action);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAction.Filters#memberOrderOf(ObjectAssociation)}
+     */
+    @Deprecated
     public static Filter<ObjectAction> memberOrderOf(ObjectAssociation association) {
-        final String assocName = association.getName();
-        final String assocId = association.getId();
-        return new Filter<ObjectAction>() {
-    
-            @Override
-            public boolean accept(ObjectAction t) {
-                final MemberOrderFacet memberOrderFacet = t.getFacet(MemberOrderFacet.class);
-                if(memberOrderFacet == null) {
-                    return false; 
-                }
-                final String memberOrderName = memberOrderFacet.name();
-                if(Strings.isNullOrEmpty(memberOrderName)) {
-                    return false;
-                }
-                return memberOrderName.equalsIgnoreCase(assocName) || memberOrderName.equalsIgnoreCase(assocId);
-            }
-        };
+        return ObjectAction.Filters.memberOrderOf(association);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueFacet.java
new file mode 100644
index 0000000..41f2f11
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueFacet.java
@@ -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.apache.isis.core.progmodel.facets.value.url;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+
+public interface URLValueFacet extends Facet {
+    java.net.URL urlValue(ObjectAdapter object);
+
+    ObjectAdapter createValue(java.net.URL value);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueSemanticsProvider.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueSemanticsProvider.java
new file mode 100644
index 0000000..05c05c0
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueSemanticsProvider.java
@@ -0,0 +1,132 @@
+/*
+ *  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.isis.core.progmodel.facets.value.url;
+
+import java.net.MalformedURLException;
+
+import org.apache.isis.applib.adapters.EncoderDecoder;
+import org.apache.isis.applib.adapters.Parser;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderAndFacetAbstract;
+import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderContext;
+
+public class URLValueSemanticsProvider extends ValueSemanticsProviderAndFacetAbstract<java.net.URL> implements URLValueFacet {
+
+    public static Class<? extends Facet> type() {
+        return URLValueFacet.class;
+    }
+
+    private static final int TYPICAL_LENGTH = 100;
+    private static final java.net.URL DEFAULT_VALUE = null; // no default
+
+    /**
+     * Required because implementation of {@link Parser} and
+     * {@link EncoderDecoder}.
+     */
+    public URLValueSemanticsProvider() {
+        this(null, null, null);
+    }
+
+    public URLValueSemanticsProvider(
+            final FacetHolder holder, 
+            final IsisConfiguration configuration, 
+            final ValueSemanticsProviderContext context) {
+        super(type(), holder, java.net.URL.class, 
+                TYPICAL_LENGTH, Immutability.IMMUTABLE, EqualByContent.HONOURED, DEFAULT_VALUE, 
+                configuration, context);
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // Parser
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    protected java.net.URL doParse(final Object context, final String entry) {
+        if (entry.trim().equals("")) {
+            return null;
+        } 
+        {
+            try {
+                return new java.net.URL(entry);
+            } catch (final MalformedURLException ex) {
+                throw new IllegalArgumentException("Not parseable as a URL ('" + entry + "')", ex);
+            }
+        }
+    }
+
+    @Override
+    public String titleString(final Object object, final Localization localization) {
+        return object != null? object.toString(): "";
+    }
+
+    @Override
+    public String titleStringWithMask(final Object object, final String usingMask) {
+        return titleString(object, null);
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // EncoderDecoder
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    protected String doEncode(final Object object) {
+        final java.net.URL url = (java.net.URL) object;
+        return url != null? url.toString(): "NULL";
+    }
+
+    @Override
+    protected java.net.URL doRestore(final String data) {
+        if("NULL".equals(data)) {
+            return null;
+        }
+        try {
+            return new java.net.URL(data);
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+
+    // //////////////////////////////////////////////////////////////////
+    // StringValueFacet
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    public java.net.URL urlValue(final ObjectAdapter object) {
+        return object == null ? null : (java.net.URL) object.getObject();
+    }
+
+    @Override
+    public ObjectAdapter createValue(final java.net.URL value) {
+        return getAdapterManager().adapterFor(value);
+    }
+
+    // /////// toString ///////
+
+    @Override
+    public String toString() {
+        return "URLValueSemanticsProvider";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueTypeFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueTypeFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueTypeFacetFactory.java
new file mode 100644
index 0000000..c5432ee
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/url/URLValueTypeFacetFactory.java
@@ -0,0 +1,42 @@
+/*
+ *  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.isis.core.progmodel.facets.value.url;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.progmodel.facets.object.value.ValueUsingValueSemanticsProviderFacetFactory;
+
+public class URLValueTypeFacetFactory extends ValueUsingValueSemanticsProviderFacetFactory<java.net.URL> {
+
+    public URLValueTypeFacetFactory() {
+        super();
+    }
+
+    @Override
+    public void process(final ProcessClassContext processClassContext) {
+        final Class<?> type = processClassContext.getCls();
+        final FacetHolder holder = processClassContext.getFacetHolder();
+
+        if (type != java.net.URL.class) {
+            return;
+        }
+        addFacets(new URLValueSemanticsProvider(holder, getConfiguration(), getContext()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 35395f4..a41a863 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -209,6 +209,7 @@ import org.apache.isis.core.progmodel.facets.value.time.TimeValueTypeFacetFactor
 import org.apache.isis.core.progmodel.facets.value.timesql.JavaSqlTimeValueTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.value.timestamp.TimeStampValueTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.value.timestampsql.JavaSqlTimeStampValueTypeFacetFactory;
+import org.apache.isis.core.progmodel.facets.value.url.URLValueTypeFacetFactory;
 
 public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract {
 
@@ -438,6 +439,7 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(JavaUtilDateValueTypeFacetFactory.class);
         addFactory(JavaSqlTimeStampValueTypeFacetFactory.class);
         addFactory(StringValueTypeFacetFactory.class);
+        addFactory(URLValueTypeFacetFactory.class);
 
         addFactory(JavaAwtImageValueTypeFacetFactory.class);
         

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
index 4643f12..4a40a03 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
@@ -19,6 +19,8 @@
 package dom.todo;
 
 import java.math.BigDecimal;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.Collections;
 import java.util.List;
 
@@ -237,6 +239,7 @@ public class ToDoItems {
     }
 
     
+    
     // //////////////////////////////////////
     // Injected Services
     // //////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/DeveloperUtilities.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/DeveloperUtilities.java b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/DeveloperUtilities.java
index 2d61a4b..f742d78 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/DeveloperUtilities.java
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/DeveloperUtilities.java
@@ -38,5 +38,6 @@ public class DeveloperUtilities extends DeveloperUtilitiesServiceDefault {
     public Blob downloadLayouts() {
         return super.downloadLayouts();
     }
+
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/ExternalLinksService.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/ExternalLinksService.java b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/ExternalLinksService.java
new file mode 100644
index 0000000..d02c201
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/java/webapp/prototyping/ExternalLinksService.java
@@ -0,0 +1,44 @@
+/**
+ *  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 webapp.prototyping;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.Prototype;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.MemberOrder;
+
+public class ExternalLinksService {
+
+    @Prototype
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(name="Prototyping", sequence="93")
+    public URL openIsisDocumentation() throws MalformedURLException {
+        return new URL("http://isis.apache.org/documentation.html");
+    }
+
+    @Prototype
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(name="Prototyping", sequence="94")
+    public URL openSourceCodeOnGithub() throws MalformedURLException {
+        return new URL("https://github.com/apache/isis/tree/master/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo");
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/8b14424c/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
index f6f9f0e..0b224b2 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
@@ -167,6 +167,7 @@ isis.services = \
                 \
                 30:webapp.prototyping.ToDoItemsFixturesService,\
                 30:webapp.prototyping.DeveloperUtilities,\
+                30:webapp.prototyping.ExternalLinksService,\
                 \
                 org.apache.isis.core.metamodel.services.bookmarks.BookmarkServiceDefault,\
                 org.apache.isis.core.runtime.services.viewmodelsupport.ViewModelSupportDefault, \