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