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 */ 019 020package org.apache.isis.core.progmodel.facets.properties.event; 021 022import java.lang.reflect.Method; 023import java.util.Comparator; 024import java.util.List; 025 026import org.apache.isis.applib.annotation.PostsPropertyChangedEvent; 027import org.apache.isis.applib.services.eventbus.PropertyChangedEvent; 028import org.apache.isis.core.commons.config.IsisConfiguration; 029import org.apache.isis.core.metamodel.facetapi.FacetUtil; 030import org.apache.isis.core.metamodel.facetapi.FeatureType; 031import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner; 032import org.apache.isis.core.metamodel.facets.Annotations; 033import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract; 034import org.apache.isis.core.metamodel.facets.FacetedMethod; 035import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet; 036import org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacet; 037import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet; 038import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet; 039import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector; 040import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware; 041import org.apache.isis.core.metamodel.spec.ObjectSpecification; 042import org.apache.isis.core.metamodel.spec.feature.Contributed; 043import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; 044import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite; 045import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting; 046import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor; 047import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures; 048 049public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware, MetaModelValidatorRefiner { 050 051 private ServicesInjector servicesInjector; 052 053 public PostsPropertyChangedEventAnnotationFacetFactory() { 054 super(FeatureType.PROPERTIES_ONLY); 055 } 056 057 @Override 058 public void process(final ProcessMethodContext processMethodContext) { 059 final Method method = processMethodContext.getMethod(); 060 FacetedMethod holder = processMethodContext.getFacetHolder(); 061 062 final PostsPropertyChangedEvent annotation = Annotations.getAnnotation(method, PostsPropertyChangedEvent.class); 063 if(annotation == null) { 064 return; 065 } 066 final PropertyOrCollectionAccessorFacet getterFacet = holder.getFacet(PropertyOrCollectionAccessorFacet.class); 067 if(getterFacet == null) { 068 return; 069 } 070 071 final PropertySetterFacet setterFacet = holder.getFacet(PropertySetterFacet.class); 072 if(setterFacet != null) { 073 final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value(); 074 FacetUtil.addFacet(new PostsPropertyChangedEventSetterFacetAnnotation(changedEventType, getterFacet, setterFacet, servicesInjector, holder)); 075 } 076 077 final PropertyClearFacet clearFacet = holder.getFacet(PropertyClearFacet.class); 078 if(clearFacet != null) { 079 final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value(); 080 FacetUtil.addFacet(new PostsPropertyChangedEventClearFacetAnnotation(changedEventType, getterFacet, clearFacet, servicesInjector, holder)); 081 } 082 } 083 084 // ////////////////////////////////////// 085 086 @Override 087 public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) { 088 metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor())); 089 } 090 091 protected Visitor newValidatorVisitor() { 092 return new MetaModelValidatorVisiting.Visitor() { 093 094 @Override 095 public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) { 096 List<OneToManyAssociation> objectCollections = objectSpec.getCollections(Contributed.EXCLUDED); 097 for (OneToManyAssociation objectCollection : objectCollections) { 098 final SortedByFacet facet = objectCollection.getFacet(SortedByFacet.class); 099 if(facet != null) { 100 final Class<? extends Comparator<?>> cls = facet.value(); 101 if(!Comparator.class.isAssignableFrom(cls)) { 102 validationFailures.add("%s#%s is annotated with @SortedBy, but the class specified '%s' is not a Comparator", objectSpec.getIdentifier().getClassName(), objectCollection.getId(), facet.value().getName()); 103 } 104 } 105 } 106 return true; 107 } 108 }; 109 } 110 111 // ////////////////////////////////////// 112 113 @Override 114 public void setServicesInjector(ServicesInjector servicesInjector) { 115 this.servicesInjector = servicesInjector; 116 } 117 118}