/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.isis.core.metamodel.facets.object.membergroups.annotprop; import java.util.List; import java.util.Properties; import org.apache.isis.applib.annotation.MemberGroupLayout; import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans; import org.apache.isis.applib.annotation.MemberGroups; import org.apache.isis.applib.annotation.Where; import org.apache.isis.applib.filter.Filters; import org.apache.isis.core.commons.config.IsisConfiguration; import org.apache.isis.core.metamodel.facetapi.FacetHolder; import org.apache.isis.core.metamodel.facetapi.FacetUtil; import org.apache.isis.core.metamodel.facetapi.FeatureType; import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner; import org.apache.isis.core.metamodel.facets.Annotations; import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract; import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet; import org.apache.isis.core.metamodel.progmodel.DeprecatedMarker; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.spec.feature.Contributed; import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor; import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures; public class MemberGroupLayoutFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner, DeprecatedMarker { public MemberGroupLayoutFacetFactory() { super(FeatureType.OBJECTS_ONLY); } @Override public void process(final ProcessClassContext processClassContext) { FacetUtil.addFacet(create(processClassContext)); } private MemberGroupLayoutFacet create(final ProcessClassContext processClassContext) { final FacetHolder holder = processClassContext.getFacetHolder(); final Class<?> cls = processClassContext.getCls(); final Properties properties = processClassContext.metadataProperties("memberGroupLayout"); if(properties != null) { return new MemberGroupLayoutFacetProperties(properties, holder); } final MemberGroupLayout mglAnnot = Annotations.getAnnotation(cls, MemberGroupLayout.class); if (mglAnnot != null) { return new MemberGroupLayoutFacetAnnotation(mglAnnot, holder); } final MemberGroups mgAnnot = Annotations.getAnnotation(cls, MemberGroups.class); if (mgAnnot != null) { return new MemberGroupsFacetAnnotation(mgAnnot, processClassContext.getFacetHolder()); } return new MemberGroupLayoutFacetFallback(holder); } @Override public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) { metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor())); } private Visitor newValidatorVisitor() { return new MetaModelValidatorVisiting.Visitor() { @Override public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) { MemberGroupLayoutFacet facet = objectSpec.getFacet(MemberGroupLayoutFacet.class); ColumnSpans columnSpans = facet.getColumnSpans(); final List<String> middle = facet.getMiddle(); final List<String> right = facet.getRight(); final int numCollections = numCollectionsOf(objectSpec); if(columnSpans.getMiddle() == 0 && !middle.isEmpty()) { validationFailures.add( "%s: @MemberGroupLayout: middle (property) column is 0 for ColumnSpans (%s), but groups have been listed (%s). NB: ColumnSpans may have been defaulted if could not be parsed.", objectSpec.getIdentifier().getClassName(), columnSpans.name(), middle); } if(columnSpans.getMiddle() > 0 && middle.isEmpty()) { // ignore; may want a gap, or there may just not be any properties to put in this column. // validationFailures.add("%s MemberGroupLayout: middle (property) column is non-zero for ColumnSpans (%s), but no groups have been listed", objectSpec.getIdentifier().getClassName(), columnSpans.name()); } if(columnSpans.getRight() == 0 && !right.isEmpty()) { validationFailures.add( "%s: @MemberGroupLayout: right (property) column is 0 for ColumnSpans (%s), but groups have been listed (%s). NB: ColumnSpans may have been defaulted if could not be parsed.", objectSpec.getIdentifier().getClassName(), columnSpans.name(), right); } if(columnSpans.getRight() > 0 && right.isEmpty()) { // ignore; may want a gap, or there may just not be any properties to put in this column. // validationFailures.add("%s MemberGroupLayout: right (property) column is non-zero for ColumnSpans (%s), but no groups have been listed", objectSpec.getIdentifier().getClassName(), columnSpans.name()); } if(columnSpans.getCollections() == 0 && numCollections>0) { validationFailures.add( "%s: @MemberGroupLayout: collections column is 0 for ColumnSpans (%s), but there are (up to) %d visible collections", objectSpec.getIdentifier().getClassName(), columnSpans.name(), numCollections); } return true; } @SuppressWarnings("unchecked") private int numCollectionsOf(ObjectSpecification objectSpec) { List<ObjectAssociation> objectCollections = objectSpec.getAssociations( Contributed.EXCLUDED, Filters.and(ObjectAssociation.Filters.staticallyVisible(Where.OBJECT_FORMS), ObjectAssociation.Filters.COLLECTIONS)); return objectCollections.size(); } }; } }