001/** 002 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 003 * This file is part of the LDP4j Project: 004 * http://www.ldp4j.org/ 005 * 006 * Center for Open Middleware 007 * http://www.centeropenmiddleware.com/ 008 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 009 * Copyright (C) 2014-2016 Center for Open Middleware. 010 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 011 * Licensed under the Apache License, Version 2.0 (the "License"); 012 * you may not use this file except in compliance with the License. 013 * You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, software 018 * distributed under the License is distributed on an "AS IS" BASIS, 019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 020 * See the License for the specific language governing permissions and 021 * limitations under the License. 022 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 023 * Artifact : org.ldp4j.framework:ldp4j-application-api:0.2.1 024 * Bundle : ldp4j-application-api-0.2.1.jar 025 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# 026 */ 027package org.ldp4j.application.data; 028 029import java.io.Serializable; 030import java.net.URI; 031import java.util.HashMap; 032import java.util.Map; 033 034import javax.xml.namespace.QName; 035 036import org.ldp4j.application.vocabulary.Term; 037 038import com.google.common.collect.ImmutableMap; 039 040public final class NamingScheme { 041 042 public enum NameType { 043 TERM(Term.class), 044 URI(URI.class), 045 QNAME(QName.class), 046 STRING(String.class), 047 NUMBER(Number.class), 048 SERIALIZABLE(Serializable.class), 049 ; 050 051 private final Class<?> clazz; 052 053 private NameType(Class<?> clazz) { 054 this.clazz = clazz; 055 } 056 057 private static NameType valueOf(Object t) { 058 for(NameType candidate:values()) { 059 if(candidate.clazz.isInstance(t)) { 060 return candidate; 061 } 062 } 063 throw new IllegalArgumentException("Invalid name type '"+t.getClass().getCanonicalName()+"'"); 064 } 065 066 @Override 067 public String toString() { 068 return clazz.getCanonicalName(); 069 } 070 071 } 072 073 private enum NamingStrategy { 074 LOCAL, 075 GLOBAL, 076 ; 077 } 078 079 private interface NameFactory { 080 081 <T extends Serializable> Name<T> create(T id); 082 083 } 084 085 private static final class GlobalNameFactory implements NameFactory { 086 087 @Override 088 public <T extends Serializable> Name<T> create(T id) { 089 return ImmutableName.newGlobalName(id); 090 } 091 092 } 093 094 private static final class LocalNameFactory implements NameFactory { 095 096 @Override 097 public <T extends Serializable> Name<T> create(T id) { 098 return ImmutableName.newLocalName(id); 099 } 100 101 } 102 103 public static final class NamingSchemeBuilder { 104 105 private Map<NameType, NamingStrategy> configuration=new HashMap<NameType, NamingStrategy>(); 106 107 private void addMappings(NamingStrategy strategy, NameType type, NameType... rest) { 108 this.configuration.put(type, strategy); 109 for(NameType r:rest) { 110 this.configuration.put(r, strategy); 111 } 112 } 113 114 public NamingSchemeBuilder withLocal(NameType type, NameType... rest) { 115 addMappings(NamingStrategy.LOCAL, type, rest); 116 return this; 117 } 118 119 public NamingSchemeBuilder withGlobal(NameType type, NameType... rest) { 120 addMappings(NamingStrategy.GLOBAL, type, rest); 121 return this; 122 } 123 124 public NamingScheme build() { 125 return new NamingScheme(this.configuration); 126 } 127 128 } 129 130 private static final Map<NamingStrategy,NameFactory> FACTORIES= 131 ImmutableMap.<NamingStrategy, NameFactory> 132 builder(). 133 put(NamingStrategy.GLOBAL, new GlobalNameFactory()). 134 put(NamingStrategy.LOCAL, new LocalNameFactory()). 135 build(); 136 137 private final Map<NameType, NamingStrategy> configuration; 138 139 private NamingScheme(Map<NameType,NamingStrategy> configuration) { 140 this.configuration = configuration; 141 } 142 143 private NameFactory getFactory(NameType type) { 144 NamingStrategy namingStrategy = configuration.get(type); 145 if(namingStrategy==null) { 146 namingStrategy=NamingStrategy.GLOBAL; 147 } 148 return FACTORIES.get(namingStrategy); 149 } 150 151 152 private static void append(StringBuilder builder, String part) { 153 if (part != null && !part.isEmpty()) { 154 if (builder.length() > 0) { 155 builder.append('.'); 156 } 157 builder.append(part); 158 } 159 } 160 161 private static String assemble(String name, String... names) { 162 StringBuilder builder=new StringBuilder(); 163 append(builder,name); 164 if(names!=null) { 165 for(String s:names) { 166 append(builder,s); 167 } 168 } 169 return builder.toString(); 170 } 171 172 private <T extends Serializable> Name<T> createName(T id) { 173 return getFactory(NameType.valueOf(id)).create(id); 174 } 175 176 public Name<URI> name(URI id) { 177 return createName(id); 178 } 179 180 public Name<QName> name(QName id) { 181 return createName(id); 182 } 183 184 public Name<Term> name(Term id) { 185 return createName(id); 186 } 187 188 /** 189 * Concatenates elements to form a dotted name, discarding null values 190 * and empty strings. 191 * 192 * @param name 193 * the first element of the name 194 * @param names 195 * the remaining elements of the name 196 * @return {@code name} and {@code names} concatenated by periods 197 */ 198 public Name<String> name(String name, String... names) { 199 return createName(assemble(name, names)); 200 } 201 202 /** 203 * Concatenates a canonical class name and elements to form a dotted name, discarding any null values or empty strings 204 * any null values or empty strings. 205 * 206 * @param clazz 207 * the first element of the name 208 * @param names 209 * the remaining elements of the name 210 * @return {@code clazz} and {@code names} concatenated by periods 211 */ 212 public Name<String> name(Class<?> clazz, String... names) { 213 return name(clazz.getCanonicalName(), names); 214 } 215 216 public <T extends Number> Name<T> name(T id) { 217 return createName(id); 218 } 219 220 public <T extends Serializable> Name<T> name(T id) { 221 return createName(id); 222 } 223 224 public static NamingSchemeBuilder builder() { 225 return new NamingSchemeBuilder(); 226 } 227 228 public static NamingScheme getDefault() { 229 return builder().build(); 230 } 231}