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.metamodel.facetapi; 021 022import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg; 023import static org.hamcrest.CoreMatchers.is; 024import static org.hamcrest.CoreMatchers.not; 025import static org.hamcrest.CoreMatchers.nullValue; 026 027import org.apache.isis.core.commons.ensure.Ensure; 028import org.apache.isis.core.commons.matchers.IsisMatchers; 029 030public abstract class FacetAbstract implements Facet { 031 032 public enum Derivation { 033 DERIVED, 034 NOT_DERIVED 035 } 036 037 private Facet underlyingFacet; 038 039 private final Class<? extends Facet> facetType; 040 private final boolean derived; 041 private FacetHolder holder; 042 043 /** 044 * Populated in {@link #setFacetHolder(FacetHolder)} if the provided holder 045 * implements {@link IdentifiedHolder}. 046 * 047 * <p> 048 * Otherwise is <tt>null</tt>. 049 */ 050 private IdentifiedHolder identifiedHolder; 051 052 @SuppressWarnings("unchecked") 053 public FacetAbstract(final Class<? extends Facet> facetType, final FacetHolder holder, final Derivation derivation) { 054 this.facetType = ensureThatArg(facetType, is(not(nullValue(Class.class)))); 055 setFacetHolder(ensureThatArg(holder, is(not(nullValue(FacetHolder.class))))); 056 this.derived = derivation == Derivation.DERIVED; 057 } 058 059 @Override 060 public final Class<? extends Facet> facetType() { 061 return facetType; 062 } 063 064 @Override 065 public FacetHolder getFacetHolder() { 066 return holder; 067 } 068 069 @Override 070 public boolean isDerived() { 071 return derived; 072 } 073 074 /** 075 * Convenience method that returns {@link #getFacetHolder()} downcast to 076 * {@link IdentifiedHolder} if the implementation does indeed inherit from 077 * {@link IdentifiedHolder}, otherwise <tt>null</tt>. 078 */ 079 public IdentifiedHolder getIdentified() { 080 return identifiedHolder; 081 } 082 083 @Override 084 public Facet getUnderlyingFacet() { 085 return underlyingFacet; 086 } 087 088 @Override 089 public void setUnderlyingFacet(final Facet underlyingFacet) { 090 if(underlyingFacet != null) { 091 Ensure.ensureThatArg(underlyingFacet.facetType(), IsisMatchers.classEqualTo(facetType)); 092 } 093 this.underlyingFacet = underlyingFacet; 094 } 095 096 /** 097 * Assume implementation is <i>not</i> a no-op. 098 * 099 * <p> 100 * No-op implementations should override and return <tt>true</tt>. 101 */ 102 @Override 103 public boolean isNoop() { 104 return false; 105 } 106 107 /** 108 * Default implementation of this method that returns <tt>true</tt>, ie 109 * should replace (none {@link #isNoop() no-op} implementations. 110 * 111 * <p> 112 * Implementations that don't wish to replace none no-op implementations 113 * should override and return <tt>false</tt>. 114 */ 115 @Override 116 public boolean alwaysReplace() { 117 return true; 118 } 119 120 @Override 121 public void setFacetHolder(final FacetHolder facetHolder) { 122 this.holder = facetHolder; 123 this.identifiedHolder = holder instanceof IdentifiedHolder ? (IdentifiedHolder) holder : null; 124 } 125 126 protected String toStringValues() { 127 return ""; 128 } 129 130 @Override 131 public String toString() { 132 String details = ""; 133 if (Validating.class.isAssignableFrom(getClass())) { 134 details += "Validating"; 135 } 136 if (Disabling.class.isAssignableFrom(getClass())) { 137 details += (details.length() > 0 ? ";" : "") + "Disabling"; 138 } 139 if (Hiding.class.isAssignableFrom(getClass())) { 140 details += (details.length() > 0 ? ";" : "") + "Hiding"; 141 } 142 if (!"".equals(details)) { 143 details = "interaction=" + details + ","; 144 } 145 146 final String className = getClass().getName(); 147 final String stringValues = toStringValues(); 148 if (getClass() != facetType()) { 149 final String facetType = facetType().getName(); 150 details += "type=" + facetType.substring(facetType.lastIndexOf('.') + 1); 151 } 152 if (!"".equals(stringValues)) { 153 details += ","; 154 } 155 return className.substring(className.lastIndexOf('.') + 1) + "[" + details + stringValues + "]"; 156 } 157 158 /** 159 * Marker interface used within {@link #toString()}. 160 */ 161 public static interface Hiding { 162 } 163 164 /** 165 * Marker interface used within {@link #toString()}. 166 */ 167 public static interface Disabling { 168 } 169 170 /** 171 * Marker interface used within {@link #toString()}. 172 */ 173 public static interface Validating { 174 } 175 176}