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, ImmutableMap.of("modify", MutatorSpec.of(Rel.MODIFY, PropertyValidateFacet.class, PropertySetterFacet.class, RestfulHttpMethod.PUT, BodyArgs.ONE), "clear",
047            MutatorSpec.of(Rel.CLEAR, PropertyValidateFacet.class, PropertyClearFacet.class, RestfulHttpMethod.DELETE, BodyArgs.NONE))) {
048        @Override
049        public ObjectSpecification specFor(final ObjectMember objectMember) {
050            return objectMember.getSpecification();
051        }
052    },
053    /**
054     * {@link #getMutators()} are keyed by
055     * {@link CollectionSemantics#getAddToKey()}
056     */
057    COLLECTION("collections/", RepresentationType.OBJECT_COLLECTION, ImmutableMap.of("addToSet", MutatorSpec.of(Rel.ADD_TO, CollectionValidateAddToFacet.class, CollectionAddToFacet.class, RestfulHttpMethod.PUT, BodyArgs.ONE), "addToList",
058            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))) {
059        @Override
060        public ObjectSpecification specFor(final ObjectMember objectMember) {
061            return objectMember.getSpecification();
062        }
063    },
064    /**
065     * {@link #getMutators()} are keyed by
066     * {@link ActionSemantics#getInvokeKey()}
067     */
068    ACTION("actions/", RepresentationType.ACTION_RESULT, ImmutableMap.of("invokeQueryOnly", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RestfulHttpMethod.GET, BodyArgs.MANY, "invoke"), "invokeIdempotent",
069            MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RestfulHttpMethod.PUT, BodyArgs.MANY, "invoke"), "invoke", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RestfulHttpMethod.POST, BodyArgs.MANY, "invoke"))) {
070        @Override
071        public ObjectSpecification specFor(final ObjectMember objectMember) {
072            final ObjectAction objectAction = (ObjectAction) objectMember;
073            return objectAction.getReturnType();
074        }
075    };
076
077    private final String urlPart;
078    private final String name;
079    private final RepresentationType representationType;
080
081    private final Map<String, MutatorSpec> mutators;
082
083    private MemberType(final String urlPart, final RepresentationType representationType, final Map<String, MutatorSpec> mutators) {
084        this.urlPart = urlPart;
085        this.representationType = representationType;
086        this.mutators = mutators;
087        name = Enums.enumToCamelCase(this);
088    }
089
090    public String getUrlPart() {
091        return urlPart;
092    }
093
094    public Map<String, MutatorSpec> getMutators() {
095        return mutators;
096    }
097
098    public abstract ObjectSpecification specFor(ObjectMember objectMember);
099
100    public boolean isProperty() {
101        return this == MemberType.PROPERTY;
102    }
103
104    public boolean isCollection() {
105        return this == MemberType.COLLECTION;
106    }
107
108    public boolean isAction() {
109        return this == MemberType.ACTION;
110    }
111
112    public static MemberType lookup(final String memberTypeName) {
113        for (final MemberType memberType : values()) {
114            if (memberType.getName().equals(memberTypeName)) {
115                return memberType;
116            }
117        }
118        return null;
119    }
120
121    public static MemberType of(final ObjectMember objectMember) {
122        return objectMember.isAction() ? ACTION : objectMember.isOneToOneAssociation() ? PROPERTY : COLLECTION;
123    }
124
125    public RepresentationType getRepresentationType() {
126        return representationType;
127    }
128
129    public String getName() {
130        return name;
131    }
132
133    public static MemberType determineFrom(final ObjectFeature objectFeature) {
134        if (objectFeature instanceof ObjectAction) {
135            return MemberType.ACTION;
136        }
137        if (objectFeature instanceof OneToOneAssociation) {
138            return MemberType.PROPERTY;
139        }
140        if (objectFeature instanceof OneToManyAssociation) {
141            return MemberType.COLLECTION;
142        }
143        return null;
144    }
145
146}