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.domainobjects;
018
019import java.util.Map;
020
021import org.apache.isis.applib.annotation.ActionSemantics;
022import org.apache.isis.applib.util.Enums;
023import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
024import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
025import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
026import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
027import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
028import org.apache.isis.core.metamodel.spec.ObjectSpecification;
029import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
030import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
031import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
032import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
033import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
034import org.apache.isis.core.progmodel.facets.actions.validate.ActionValidationFacet;
035import org.apache.isis.core.progmodel.facets.collections.validate.CollectionValidateAddToFacet;
036import org.apache.isis.core.progmodel.facets.collections.validate.CollectionValidateRemoveFromFacet;
037import org.apache.isis.core.progmodel.facets.properties.validate.PropertyValidateFacet;
038import org.apache.isis.viewer.restfulobjects.applib.Rel;
039import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
040import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
041
042import com.google.common.collect.ImmutableMap;
043
044public enum MemberType {
045
046    PROPERTY("properties/", RepresentationType.OBJECT_PROPERTY,
047            ImmutableMap.of(
048                    "modify", MutatorSpec.of(Rel.MODIFY, PropertyValidateFacet.class, PropertySetterFacet.class, RestfulHttpMethod.PUT, BodyArgs.ONE),
049                    "clear", MutatorSpec.of(Rel.CLEAR, PropertyValidateFacet.class, PropertyClearFacet.class, RestfulHttpMethod.DELETE, BodyArgs.NONE))) {
050        @Override
051        public ObjectSpecification specFor(final ObjectMember objectMember) {
052            return objectMember.getSpecification();
053        }
054    },
055    /**
056     * {@link #getMutators()} are keyed by
057     * {@link CollectionSemantics#getAddToKey()}
058     */
059    COLLECTION("collections/", RepresentationType.OBJECT_COLLECTION,
060            ImmutableMap.of(
061                    "addToSet", MutatorSpec.of(Rel.ADD_TO, CollectionValidateAddToFacet.class, CollectionAddToFacet.class, RestfulHttpMethod.PUT, BodyArgs.ONE),
062                    "addToList", MutatorSpec.of(Rel.ADD_TO, CollectionValidateAddToFacet.class, CollectionAddToFacet.class, RestfulHttpMethod.POST, BodyArgs.ONE), "removeFrom", MutatorSpec.of(Rel.REMOVE_FROM, CollectionValidateRemoveFromFacet.class, CollectionRemoveFromFacet.class, RestfulHttpMethod.DELETE, BodyArgs.ONE))) {
063        @Override
064        public ObjectSpecification specFor(final ObjectMember objectMember) {
065            return objectMember.getSpecification();
066        }
067    },
068    /**
069     * {@link #getMutators()} are keyed by
070     * {@link ActionSemantics#getInvokeKey()}
071     */
072    ACTION("actions/", RepresentationType.OBJECT_ACTION,
073            ImmutableMap.of(
074                    "invokeQueryOnly", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RestfulHttpMethod.GET, BodyArgs.MANY, "invoke"),
075                    "invokeIdempotent", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RestfulHttpMethod.PUT, BodyArgs.MANY, "invoke"),
076                    "invoke", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RestfulHttpMethod.POST, BodyArgs.MANY, "invoke"))) {
077        @Override
078        public ObjectSpecification specFor(final ObjectMember objectMember) {
079            final ObjectAction objectAction = (ObjectAction) objectMember;
080            return objectAction.getReturnType();
081        }
082    };
083
084    private final String urlPart;
085    private final String name;
086    private final RepresentationType representationType;
087
088    private final Map<String, MutatorSpec> mutators;
089
090    private MemberType(final String urlPart, final RepresentationType representationType, final Map<String, MutatorSpec> mutators) {
091        this.urlPart = urlPart;
092        this.representationType = representationType;
093        this.mutators = mutators;
094        name = Enums.enumToCamelCase(this);
095    }
096
097    public String getUrlPart() {
098        return urlPart;
099    }
100
101    public Map<String, MutatorSpec> getMutators() {
102        return mutators;
103    }
104
105    public abstract ObjectSpecification specFor(ObjectMember objectMember);
106
107    public boolean isProperty() {
108        return this == MemberType.PROPERTY;
109    }
110
111    public boolean isCollection() {
112        return this == MemberType.COLLECTION;
113    }
114
115    public boolean isAction() {
116        return this == MemberType.ACTION;
117    }
118
119    public static MemberType lookup(final String memberTypeName) {
120        for (final MemberType memberType : values()) {
121            if (memberType.getName().equals(memberTypeName)) {
122                return memberType;
123            }
124        }
125        return null;
126    }
127
128    public static MemberType of(final ObjectMember objectMember) {
129        return objectMember.isAction() ? ACTION : objectMember.isOneToOneAssociation() ? PROPERTY : COLLECTION;
130    }
131
132    public RepresentationType getRepresentationType() {
133        return representationType;
134    }
135
136    public String getName() {
137        return name;
138    }
139
140    public static MemberType determineFrom(final ObjectFeature objectFeature) {
141        if (objectFeature instanceof ObjectAction) {
142            return MemberType.ACTION;
143        }
144        if (objectFeature instanceof OneToOneAssociation) {
145            return MemberType.PROPERTY;
146        }
147        if (objectFeature instanceof OneToManyAssociation) {
148            return MemberType.COLLECTION;
149        }
150        return null;
151    }
152
153}