001/*- 002 * #%L 003 * Smile CDR - CDR 004 * %% 005 * Copyright (C) 2016 - 2026 Smile CDR, Inc. 006 * %% 007 * All rights reserved. 008 * #L% 009 */ 010package ca.cdr.api.security.permission; 011 012import jakarta.annotation.Nonnull; 013import jakarta.annotation.Nullable; 014 015import java.util.Optional; 016 017import static org.apache.commons.lang3.StringUtils.isNotBlank; 018 019/** 020 * An operation name with an optional instance filter. 021 * e.g. $meta-add or $meta-add?category=vital-signs 022 */ 023public final class OperationOnAnyInstance extends PermissionArgumentValue 024 implements PermissionArgumentFormat.IOperationRestriction, PermissionArgumentFormat.IOptionalFilterRestriction { 025 // final for optimizer 026 027 private final String myOperationName; 028 029 @Nullable 030 private final String myFilter; 031 032 OperationOnAnyInstance(String theOperationName, @Nullable String theFilter) { 033 myOperationName = theOperationName; 034 myFilter = theFilter; 035 } 036 037 @Override 038 public String getOperationName() { 039 return myOperationName; 040 } 041 042 @Nonnull 043 @Override 044 String getStringValue() { 045 StringBuilder sb = new StringBuilder(); 046 sb.append(myOperationName); 047 if (myFilter != null) { 048 sb.append("?").append(myFilter); 049 } 050 return sb.toString(); 051 } 052 053 @Override 054 public Optional<String> getFilter() { 055 return Optional.ofNullable(myFilter); 056 } 057 058 static final class Format implements PermissionArgumentFormat<OperationOnAnyInstance> { 059 060 @Override 061 public Class<OperationOnAnyInstance> getType() { 062 return OperationOnAnyInstance.class; 063 } 064 065 @Override 066 public @Nonnull Optional<OperationOnAnyInstance> parse( 067 String theArgumentString, @Nonnull IdBuilder theIdBuilder) { 068 // e.g. $meta-add or $meta-add?category=vital-signs 069 if (isNotBlank(theArgumentString)) { 070 String operationName; 071 String filter; 072 int splitIdx = theArgumentString.indexOf('?'); 073 if (splitIdx == 0) { 074 // invalid - filter only (i.e. ?category=vital-signs) 075 return Optional.empty(); 076 } else if (splitIdx == -1) { 077 // valid - no filter (i.e. $meta-add) 078 operationName = theArgumentString; 079 filter = null; 080 } else { 081 // valid - has filter (i.e. $meta-add?category=vital-signs) 082 operationName = theArgumentString.substring(0, splitIdx); 083 filter = theArgumentString.substring(splitIdx + 1); 084 } 085 086 return Optional.of(new OperationOnAnyInstance(operationName, filter)); 087 } 088 089 return Optional.empty(); 090 } 091 092 @Override 093 public @Nonnull String format(@Nonnull OperationOnAnyInstance theArgument) { 094 return theArgument.getStringValue(); 095 } 096 } 097}