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.object.title.annotation; 021 022import java.lang.reflect.Method; 023import java.util.List; 024 025import com.google.common.base.Function; 026import com.google.common.base.Objects; 027import com.google.common.base.Strings; 028 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import org.apache.isis.applib.annotation.Title; 033import org.apache.isis.applib.profiles.Localization; 034import org.apache.isis.core.commons.lang.StringExtensions; 035import org.apache.isis.core.metamodel.adapter.ObjectAdapter; 036import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; 037import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils; 038import org.apache.isis.core.metamodel.facetapi.FacetHolder; 039import org.apache.isis.core.metamodel.facets.object.title.TitleFacetAbstract; 040 041public class TitleFacetViaTitleAnnotation extends TitleFacetAbstract { 042 043 private static final Logger LOG = LoggerFactory.getLogger(TitleFacetViaTitleAnnotation.class); 044 private final List<TitleComponent> components; 045 private final AdapterManager adapterManager; 046 047 public static class TitleComponent { 048 public static final Function<? super Method, ? extends TitleComponent> FROM_METHOD = new Function<Method, TitleComponent>() { 049 050 @Override 051 public TitleComponent apply(final Method input) { 052 return TitleComponent.of(input); 053 } 054 }; 055 056 private final String prepend; 057 private final String append; 058 private final Method method; 059 private final int abbreviateTo; 060 061 private TitleComponent(final String prepend, final String append, final Method method, final int abbreviateTo) { 062 super(); 063 this.prepend = prepend; 064 this.append = append; 065 this.method = method; 066 this.abbreviateTo = abbreviateTo; 067 } 068 069 public String getPrepend() { 070 return prepend; 071 } 072 073 public String getAppend() { 074 return append; 075 } 076 077 public Method getMethod() { 078 return method; 079 } 080 081 public static TitleComponent of(final Method method) { 082 final Title annotation = method.getAnnotation(Title.class); 083 final String prepend = annotation != null ? annotation.prepend() : " "; 084 final String append = annotation != null ? annotation.append() : ""; 085 final int abbreviateTo = annotation != null ? annotation.abbreviatedTo() : Integer.MAX_VALUE; 086 return new TitleComponent(prepend, append, method, abbreviateTo); 087 } 088 } 089 090 public TitleFacetViaTitleAnnotation(final List<TitleComponent> components, final FacetHolder holder, final AdapterManager adapterManager) { 091 super(holder); 092 this.components = components; 093 this.adapterManager = adapterManager; 094 } 095 096 @Override 097 public String title(final ObjectAdapter targetAdapter, final Localization localization) { 098 return title(null, targetAdapter, localization); 099 } 100 101 private String titleOf(final ObjectAdapter adapter) { 102 if (adapter == null) { 103 return null; 104 } 105 return adapter.titleString(null); 106 } 107 108 public List<TitleComponent> getComponents() { 109 return components; 110 } 111 112 private static String abbreviated(final String str, final int maxLength) { 113 return str.length() < maxLength ? str : str.substring(0, maxLength - 3) + "..."; 114 } 115 116 @Override 117 public String title(ObjectAdapter contextAdapter, ObjectAdapter targetAdapter, Localization localization) { 118 final StringBuilder stringBuilder = new StringBuilder(); 119 120 try { 121 for (final TitleComponent component : this.components) { 122 final Object titlePart = AdapterInvokeUtils.invoke(component.getMethod(), targetAdapter); 123 if (titlePart == null) { 124 continue; 125 } 126 // ignore context, if provided 127 final ObjectAdapter titlePartAdapter = adapterManager.adapterFor(titlePart); 128 if(Objects.equal(contextAdapter, titlePartAdapter)) { 129 continue; 130 } 131 String title = titleOf(titlePartAdapter); 132 if (Strings.isNullOrEmpty(title)) { 133 // ... use the toString() otherwise 134 // (mostly for benefit of testing...) 135 title = titlePart.toString().trim(); 136 } 137 if(Strings.isNullOrEmpty(title)) { 138 continue; 139 } 140 stringBuilder.append(component.getPrepend()); 141 stringBuilder.append(abbreviated(title, component.abbreviateTo)); 142 stringBuilder.append(component.getAppend()); 143 } 144 145 return stringBuilder.toString().trim(); 146 } catch (final RuntimeException ex) { 147 LOG.warn("Title failure", ex); 148 return "Failed Title"; 149 } 150 } 151}