001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.isis.viewer.restfulobjects.rendering.domaintypes; 018 019import java.util.List; 020 021import org.apache.isis.core.metamodel.spec.ObjectSpecification; 022import org.apache.isis.core.metamodel.spec.feature.ObjectAction; 023import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer.Contributed; 024import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; 025import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; 026import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; 027import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; 028import org.apache.isis.viewer.restfulobjects.applib.Rel; 029import org.apache.isis.viewer.restfulobjects.applib.RepresentationType; 030import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder; 031import org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs; 032import org.apache.isis.viewer.restfulobjects.rendering.RendererContext; 033import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract; 034import org.codehaus.jackson.node.NullNode; 035 036import com.google.common.base.Strings; 037 038public class DomainTypeReprRenderer extends ReprRendererAbstract<DomainTypeReprRenderer, ObjectSpecification> { 039 040 public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectSpecification objectSpec) { 041 final String typeFullName = objectSpec.getSpecId().asString(); 042 final String url = "domain-types/" + typeFullName; 043 return LinkBuilder.newBuilder(resourceContext, rel.getName(), RepresentationType.DOMAIN_TYPE, url); 044 } 045 046 private ObjectSpecification objectSpecification; 047 048 public DomainTypeReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final JsonRepresentation representation) { 049 super(resourceContext, linkFollower, RepresentationType.DOMAIN_TYPE, representation); 050 } 051 052 @Override 053 public DomainTypeReprRenderer with(final ObjectSpecification objectSpecification) { 054 this.objectSpecification = objectSpecification; 055 return cast(this); 056 } 057 058 @Override 059 public JsonRepresentation render() { 060 061 if (objectSpecification == null) { 062 throw new IllegalStateException("ObjectSpecification not specified"); 063 } 064 065 // self 066 if (includesSelf) { 067 final JsonRepresentation selfLink = newLinkToBuilder(getRendererContext(), Rel.SELF, objectSpecification).build(); 068 getLinks().arrayAdd(selfLink); 069 } 070 071 representation.mapPut("canonicalName", objectSpecification.getFullIdentifier()); 072 addMembers(); 073 074 addTypeActions(); 075 076 putExtensionsNames(); 077 putExtensionsDescriptionIfAvailable(); 078 putExtensionsIfService(); 079 080 return representation; 081 } 082 083 private void addMembers() { 084 final JsonRepresentation membersList = JsonRepresentation.newArray(); 085 representation.mapPut("members", membersList); 086 final List<ObjectAssociation> associations = objectSpecification.getAssociations(); 087 for (final ObjectAssociation association : associations) { 088 if (association.isOneToOneAssociation()) { 089 final OneToOneAssociation property = (OneToOneAssociation) association; 090 final LinkBuilder linkBuilder = PropertyDescriptionReprRenderer.newLinkToBuilder(getRendererContext(), Rel.PROPERTY, objectSpecification, property); 091 membersList.arrayAdd(linkBuilder.build()); 092 } else if (association.isOneToManyAssociation()) { 093 final OneToManyAssociation collection = (OneToManyAssociation) association; 094 final LinkBuilder linkBuilder = CollectionDescriptionReprRenderer.newLinkToBuilder(getRendererContext(), Rel.PROPERTY, objectSpecification, collection); 095 membersList.arrayAdd(linkBuilder.build()); 096 } 097 } 098 final List<ObjectAction> actions = objectSpecification.getObjectActions(Contributed.INCLUDED); 099 for (final ObjectAction action : actions) { 100 final LinkBuilder linkBuilder = ActionDescriptionReprRenderer.newLinkToBuilder(getRendererContext(), Rel.ACTION, objectSpecification, action); 101 membersList.arrayAdd(linkBuilder.build()); 102 } 103 } 104 105 private JsonRepresentation getTypeActions() { 106 JsonRepresentation typeActions = representation.getArray("typeActions"); 107 if (typeActions == null) { 108 typeActions = JsonRepresentation.newArray(); 109 representation.mapPut("typeActions", typeActions); 110 } 111 return typeActions; 112 } 113 114 private void addTypeActions() { 115 getTypeActions().arrayAdd(linkToIsSubtypeOf()); 116 getTypeActions().arrayAdd(linkToIsSupertypeOf()); 117 } 118 119 private JsonRepresentation linkToIsSubtypeOf() { 120 final String url = "domain-types/" + objectSpecification.getSpecId().asString() + "/type-actions/isSubtypeOf/invoke"; 121 122 final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getRendererContext(), Rel.INVOKE.andParam("typeaction", "isSubtypeOf"), RepresentationType.TYPE_ACTION_RESULT, url); 123 final JsonRepresentation arguments = argumentsTo(getRendererContext(), "supertype", null); 124 final JsonRepresentation link = linkBuilder.withArguments(arguments).build(); 125 return link; 126 } 127 128 private JsonRepresentation linkToIsSupertypeOf() { 129 final String url = "domain-types/" + objectSpecification.getSpecId().asString() + "/type-actions/isSupertypeOf/invoke"; 130 131 final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getRendererContext(), Rel.INVOKE.andParam("typeaction", "isSupertypeOf"), RepresentationType.TYPE_ACTION_RESULT, url); 132 final JsonRepresentation arguments = argumentsTo(getRendererContext(), "subtype", null); 133 final JsonRepresentation link = linkBuilder.withArguments(arguments).build(); 134 return link; 135 } 136 137 public static JsonRepresentation argumentsTo(final RendererContext resourceContext, final String paramName, final ObjectSpecification objectSpec) { 138 final JsonRepresentation arguments = JsonRepresentation.newMap(); 139 final JsonRepresentation link = JsonRepresentation.newMap(); 140 arguments.mapPut(paramName, link); 141 if (objectSpec != null) { 142 link.mapPut("href", resourceContext.urlFor("domain-types/" + objectSpec.getSpecId().asString())); 143 } else { 144 link.mapPut("href", NullNode.instance); 145 } 146 return arguments; 147 } 148 149 protected void putExtensionsNames() { 150 final String singularName = objectSpecification.getSingularName(); 151 getExtensions().mapPut("friendlyName", singularName); 152 153 final String pluralName = objectSpecification.getPluralName(); 154 getExtensions().mapPut("pluralName", pluralName); 155 } 156 157 protected void putExtensionsDescriptionIfAvailable() { 158 final String description = objectSpecification.getDescription(); 159 if (!Strings.isNullOrEmpty(description)) { 160 getExtensions().mapPut("description", description); 161 } 162 } 163 164 protected void putExtensionsIfService() { 165 getExtensions().mapPut("isService", objectSpecification.isService()); 166 } 167 168}