/* * 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.services.metamodel; import java.util.Collection; import java.util.Collections; import java.util.List; import com.google.common.collect.Lists; import org.datanucleus.enhancement.Persistable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.isis.applib.annotation.DomainService; import org.apache.isis.applib.annotation.NatureOfService; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.services.bookmark.Bookmark; import org.apache.isis.applib.services.grid.GridService; import org.apache.isis.applib.services.metamodel.DomainMember; import org.apache.isis.applib.services.metamodel.MetaModelService3; import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet; import org.apache.isis.core.metamodel.spec.ObjectSpecId; 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.ObjectAction; import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; import org.apache.isis.core.metamodel.specloader.SpecificationLoader; @DomainService( nature = NatureOfService.DOMAIN, menuOrder = "" + Integer.MAX_VALUE ) public class MetaModelServiceDefault implements MetaModelService3 { @SuppressWarnings("unused") private final static Logger LOG = LoggerFactory.getLogger(MetaModelServiceDefault.class); @Programmatic public Class<?> fromObjectType(final String objectType) { if(objectType == null) { return null; } final ObjectSpecId objectSpecId = new ObjectSpecId(objectType); final ObjectSpecification objectSpecification = specificationLookup.lookupBySpecId(objectSpecId); return objectSpecification != null? objectSpecification.getCorrespondingClass(): null; } @Override public String toObjectType(final Class<?> domainType) { if(domainType == null) { return null; } final ObjectSpecification objectSpecification = specificationLookup.loadSpecification(domainType); final ObjectSpecIdFacet objectSpecIdFacet = objectSpecification.getFacet(ObjectSpecIdFacet.class); final ObjectSpecId objectSpecId = objectSpecIdFacet.value(); return objectSpecId.asString(); } @Override public void rebuild(final Class<?> domainType) { specificationLookup.invalidateCache(domainType); gridService.remove(domainType); final ObjectSpecification objectSpecification = specificationLookup.loadSpecification(domainType); // ensure the spec is fully rebuilt objectSpecification.getObjectActions(Contributed.INCLUDED); objectSpecification.getAssociations(Contributed.INCLUDED); } // ////////////////////////////////////// @Programmatic public List<DomainMember> export() { final Collection<ObjectSpecification> specifications = specificationLookup.allSpecifications(); final List<DomainMember> rows = Lists.newArrayList(); for (final ObjectSpecification spec : specifications) { if (exclude(spec)) { continue; } final List<ObjectAssociation> properties = spec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES); for (final ObjectAssociation property : properties) { final OneToOneAssociation otoa = (OneToOneAssociation) property; if (exclude(otoa)) { continue; } rows.add(new DomainMemberDefault(spec, otoa)); } final List<ObjectAssociation> associations = spec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.COLLECTIONS); for (final ObjectAssociation collection : associations) { final OneToManyAssociation otma = (OneToManyAssociation) collection; if (exclude(otma)) { continue; } rows.add(new DomainMemberDefault(spec, otma)); } final List<ObjectAction> actions = spec.getObjectActions(Contributed.INCLUDED); for (final ObjectAction action : actions) { if (exclude(action)) { continue; } rows.add(new DomainMemberDefault(spec, action)); } } Collections.sort(rows); return rows; } protected boolean exclude(final OneToOneAssociation property) { return false; } protected boolean exclude(final OneToManyAssociation collection) { return false; } protected boolean exclude(final ObjectAction action) { return false; } protected boolean exclude(final ObjectSpecification spec) { return isBuiltIn(spec) || spec.isAbstract(); } protected boolean isBuiltIn(final ObjectSpecification spec) { final String className = spec.getFullIdentifier(); return className.startsWith("java") || className.startsWith("org.joda"); } // ////////////////////////////////////// @Override public Sort sortOf(final Class<?> domainType) { return sortOf(domainType, Mode.STRICT); } @Override public Sort sortOf( final Class<?> domainType, final Mode mode) { if(domainType == null) { return null; } final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainType); if(objectSpec.isService()) { return Sort.DOMAIN_SERVICE; } if(objectSpec.isViewModel()) { return Sort.VIEW_MODEL; } if(objectSpec.isValue()) { return Sort.VALUE; } if(objectSpec.isMixin()) { return Sort.VALUE; } if(objectSpec.isParentedOrFreeCollection()) { return Sort.COLLECTION; } final Class<?> correspondingClass = objectSpec.getCorrespondingClass(); if(Persistable.class.isAssignableFrom(correspondingClass)) { return Sort.JDO_ENTITY; } if(mode == Mode.RELAXED) { return Sort.UNKNOWN; } throw new IllegalArgumentException(String.format( "Unable to determine what sort of domain object is '%s'", objectSpec.getFullIdentifier())); } @Override public Sort sortOf(final Bookmark bookmark) { return sortOf(bookmark, Mode.STRICT); } @Override public Sort sortOf(final Bookmark bookmark, final Mode mode) { if(bookmark == null) { return null; } final Class<?> domainType; switch (mode) { case RELAXED: try { domainType = this.fromObjectType(bookmark.getObjectType()); } catch (Exception e) { return Sort.UNKNOWN; } break; case STRICT: // fall through to... default: domainType = this.fromObjectType(bookmark.getObjectType()); break; } return sortOf(domainType, mode); } @javax.inject.Inject SpecificationLoader specificationLookup; @javax.inject.Inject GridService gridService; }