001/* 002 * (C) Copyright 2020 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bdelbosc 018 */ 019package org.nuxeo.lib.stream.log; 020 021import java.util.Objects; 022import java.util.regex.Pattern; 023 024/** 025 * An identifier composed of a namespace and a specific name with 2 string representations:<br> 026 * - an uniform resource name (urn) represented as a relative path: {@code namespace/name}<br> 027 * - an identifier (id): encode the urn as {@code namespace-name}<br> 028 * 029 * 030 * When there is no namespace, URN and id are identical. 031 * 032 * @since 11.1 033 */ 034public class Name { 035 public static final String NAMESPACE_GLOBAL = "_GLOBAL_"; 036 037 public static final String NAMESPACE_URN_SEP = "/"; 038 039 public static final String NAMESPACE_ID_SEP = "-"; 040 041 protected static final Pattern VALID_NAMESPACE_PATTERN = Pattern.compile("[A-Za-z][A-Za-z0-9_]*"); 042 043 protected static final Pattern VALID_LOG_NAME_PATTERN = Pattern.compile("[A-Za-z0-9][A-Za-z0-9_\\-]*"); 044 045 protected static final Pattern VALID_LOG_NAME_WITHOUT_NS_PATTERN = Pattern.compile("[A-Za-z0-9][A-Za-z0-9_]*"); 046 047 protected final String namespace; 048 049 protected final String name; 050 051 protected final String id; 052 053 protected final String urn; 054 055 private Name(String namespace, String name) { 056 checkNameSpace(namespace); 057 this.namespace = namespace; 058 this.name = name; 059 if (NAMESPACE_GLOBAL.equals(namespace)) { 060 checkLogNameWithoutNamespace(name); 061 this.id = name; 062 this.urn = name; 063 } else { 064 checkLogName(name); 065 this.id = namespace + NAMESPACE_ID_SEP + name; 066 this.urn = namespace + NAMESPACE_URN_SEP + name; 067 } 068 } 069 070 public static Name of(String namespace, String name) { 071 return new Name(namespace, name); 072 } 073 074 public static Name ofUrn(String urn) { 075 Objects.requireNonNull(urn, "Null URN"); 076 int pos = urn.indexOf(NAMESPACE_URN_SEP); 077 if (pos < 0) { 078 return new Name(NAMESPACE_GLOBAL, urn); 079 } 080 return new Name(urn.substring(0, pos), urn.substring(pos + 1)); 081 } 082 083 public static Name ofId(String id) { 084 Objects.requireNonNull(id, "Null id"); 085 int pos = id.indexOf(NAMESPACE_ID_SEP); 086 if (pos < 0) { 087 return new Name(NAMESPACE_GLOBAL, id); 088 } 089 return new Name(id.substring(0, pos), id.substring(pos + 1)); 090 } 091 092 public static String idOfUrn(String urn) { 093 return Name.ofUrn(urn).getId(); 094 } 095 096 public static String urnOfId(String id) { 097 return Name.ofId(id).getUrn(); 098 } 099 100 public String getNamespace() { 101 return namespace; 102 } 103 104 public String getName() { 105 return name; 106 } 107 108 public String getId() { 109 return id; 110 } 111 112 public String getUrn() { 113 return urn; 114 } 115 116 @Override 117 public String toString() { 118 return "Name{id='" + id + "', urn='" + urn + "'}"; 119 } 120 121 protected static void checkLogName(String name) { 122 if (!VALID_LOG_NAME_PATTERN.matcher(name).matches()) { 123 throw new IllegalArgumentException("Invalid name: '" + name + "'."); 124 } 125 } 126 127 protected static void checkLogNameWithoutNamespace(String name) { 128 if (!VALID_LOG_NAME_WITHOUT_NS_PATTERN.matcher(name).matches()) { 129 throw new IllegalArgumentException("Invalid name without namespace: '" + name + "'"); 130 } 131 } 132 133 protected static void checkNameSpace(String name) { 134 if (!VALID_NAMESPACE_PATTERN.matcher(name).matches() && !NAMESPACE_GLOBAL.equals(name)) { 135 throw new IllegalArgumentException("Invalid namespace: '" + name + "'"); 136 } 137 } 138 139 @Override 140 public boolean equals(Object o) { 141 if (this == o) { 142 return true; 143 } 144 if (o == null || getClass() != o.getClass()) { 145 return false; 146 } 147 Name otherName = (Name) o; 148 return Objects.equals(urn, otherName.urn); 149 } 150 151 @Override 152 public int hashCode() { 153 return Objects.hash(urn); 154 } 155}