/*- * ============LICENSE_START======================================================= * org.onap.dmaap * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.onap.dmaap.dbcapi.model; import com.google.common.base.Objects; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.json.simple.*; import org.json.simple.parser.*; import javax.xml.bind.annotation.XmlRootElement; import org.onap.dmaap.dbcapi.util.DmaapConfig; import io.swagger.annotations.ApiModelProperty; import org.onap.dmaap.dbcapi.service.DmaapService; import org.onap.dmaap.dbcapi.service.TopicService; @XmlRootElement public class Topic extends DmaapObject { @ApiModelProperty( value="Fully Qualified Topic Name constructed by dbcapi, following the rules for `fqtnStyle`") private String fqtn; @ApiModelProperty( value="the short name used by humans, and utilized to construct the `FQTN`") private String topicName; @ApiModelProperty( value="a description of what this Topic is used for") private String topicDescription; private String tnxEnabled; @ApiModelProperty( value="a label used to identify who requested this `Topic` to be provisioned. In the future this " + "may be an AAF Identity.") private String owner; @ApiModelProperty( value="a reference to an identifier that describes a data format used for this `Topic`") private String formatUuid; @ApiModelProperty( value="An indicator for how this `Topic` should be replicated when there are more than one `MR_Cluster` instances") private ReplicationType replicationCase; @ApiModelProperty( value="the URL of an outside MR instance") private String globalMrURL; // optional: URL of global MR to replicate to/from @ApiModelProperty( value="the construction rule for the `fqtn` field") private FqtnType fqtnStyle; @ApiModelProperty( value="a hook for any versioning needed for managing a `Topic` over time") private String version; @ApiModelProperty( value="the kafka attribute for specifying the number of partitions") private String partitionCount; @ApiModelProperty( value="the kafka attribute for specifying replication within an `MR_Cluster` instance") private String replicationCount; @ApiModelProperty( value="a value generated by dbcapi, this AAF Role has permission to publish to this `Topic`") private String publisherRole; @ApiModelProperty( value="a value generated by dbcapi, this AAF Role has permission to subscribe to this `Topic`") private String subscriberRole; @ApiModelProperty( value="an array of `MR_Client` objects associated to this `Topic`") private List clients; private static Dmaap dmaap = new DmaapService().getDmaap(); private static String defaultPartitionCount; private static String defaultReplicationCount; // during unit testing, discovered that presence of dots in some values // creates an unplanned topic namespace as we compose the FQTN. // this may create sensitivity (i.e. 403) for subsequent creation of AAF perms, so best to not allow it private static String removeDots( String source, String def ) { if ( source == null || source.isEmpty()) { return def; } return source.replaceAll("\\.", "_"); } // // utility function to generate the FQTN of a topic public String genFqtn( ) { DmaapConfig dc = (DmaapConfig)DmaapConfig.getConfig(); String projectId = dc.getProperty("MR.projectID", "99999"); CharSequence signal = "."; String ret; if ( this.getTopicName().contains( signal )) { // presence of a dot indicates the name is already fully qualified ret = this.getTopicName(); } else { // these vars may not contain dots String p = removeDots( projectId, "90909"); String v = removeDots( this.getVersion(), "v1"); switch( this.getFqtnStyle() ) { case FQTN_PROJECTID_VERSION_FORMAT: ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + p + "-" + this.getTopicName() + "-" + v; break; case FQTN_PROJECTID_FORMAT: ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + p + "-" + this.getTopicName(); break; case FQTN_LEGACY_FORMAT: default: // for backwards compatibility ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + this.getTopicName(); break; } } return ret; } public Topic() { super(); this.clients = new ArrayList<>(); this.lastMod = new Date(); this.replicationCase = ReplicationType.Validator("none"); this.setLastMod(); logger.debug( "Topic constructor " + this.lastMod ); } public Topic(String fqtn, String topicName, String topicDescription, String tnxEnabled, String owner) { super(); this.fqtn = fqtn; this.topicName = topicName; this.topicDescription = topicDescription; this.tnxEnabled = tnxEnabled; this.owner = owner; this.init(); this.setLastMod(); logger.debug( "Topic constructor w args " + this.getLastMod() ); } public Topic init() { DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); defaultPartitionCount = p.getProperty( "MR.partitionCount", "2"); defaultReplicationCount = p.getProperty( "MR.replicationCount", "1"); this.setStatus( DmaapObject_Status.NEW ); this.replicationCase = ReplicationType.Validator("none"); this.fqtnStyle = FqtnType.Validator("none"); this.setPartitionCount( defaultPartitionCount ); this.setReplicationCount( defaultReplicationCount ); return this; } // expects a String in JSON format, with known fields to populate Topic object public Topic ( String json ) { JSONParser parser = new JSONParser(); JSONObject jsonObj; try { jsonObj = (JSONObject) parser.parse( json ); } catch ( ParseException pe ) { logger.error( "Error parsing provisioning data: " + json ); this.setStatus( DmaapObject_Status.INVALID ); return; } this.setFqtn( (String) jsonObj.get( "fqtn" ) ); this.setTopicName( (String) jsonObj.get( "topicName" ) ); this.setTopicDescription( (String) jsonObj.get( "topicDescription" )); this.setOwner( (String) jsonObj.get( "owner" ) ); this.setStatus( (String) jsonObj.get( "status" ) ); this.setReplicationCase( ReplicationType.Validator( (String) jsonObj.get( "replicationCase" ) )); this.setFqtnStyle( FqtnType.Validator( (String) jsonObj.get( "fqtnStyle" ) ) ); this.setPartitionCount( (String) jsonObj.get("partitionCount")); } public String getFqtn() { return fqtn; } public void setFqtn(String fqtn) { this.fqtn = fqtn; } public String getTopicName() { return topicName; } public void setTopicName(String topicName) { this.topicName = topicName; } public String getTopicDescription() { return topicDescription; } public void setTopicDescription(String topicDescription) { this.topicDescription = topicDescription; } public String getTnxEnabled() { return tnxEnabled; } public void setTnxEnabled(String tnxEnabled) { this.tnxEnabled = tnxEnabled; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public String getPartitionCount() { return partitionCount; } public void setPartitionCount(String partitions) { this.partitionCount = partitions; } public String getReplicationCount() { return replicationCount; } public void setReplicationCount(String replicationCount) { this.replicationCount = replicationCount; } public void setClients(List clients) { this.clients = clients; } public List getClients() { return clients; } @ApiModelProperty( hidden=true ) public int getNumClients() { if ( this.clients == null ) { return 0; } return this.clients.size(); } public String getFormatUuid() { return formatUuid; } public void setFormatUuid(String formatUuid) { this.formatUuid = formatUuid; } public ReplicationType getReplicationCase() { return replicationCase; } public void setReplicationCase(ReplicationType t) { this.replicationCase = t; } public FqtnType getFqtnStyle() { return fqtnStyle; } public void setFqtnStyle(FqtnType t) { this.fqtnStyle = t; } public String getGlobalMrURL() { return globalMrURL; } public void setGlobalMrURL(String globalMrURL) { this.globalMrURL = globalMrURL; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getPublisherRole() { return publisherRole; } public void setPublisherRole(String publisherRole) { this.publisherRole = publisherRole; } public String getSubscriberRole() { return subscriberRole; } public void setSubscriberRole(String subscriberRole) { this.subscriberRole = subscriberRole; } public String toProvJSON() { StringBuilder str = new StringBuilder(); str.append("{ \"topicName\": \""); str.append( this.getFqtn() ); str.append( "\", \"topicDescription\": \""); str.append( this.getTopicDescription()); str.append( "\", \"partitionCount\": \""); str.append( this.getPartitionCount()); str.append( "\", \"replicationCount\": \""); str.append( this.getReplicationCount()); str.append( "\" } "); logger.info( str.toString() ); return str.toString(); } @ApiModelProperty( hidden=true ) public byte[] getBytes() { return toProvJSON().getBytes(StandardCharsets.UTF_8); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Topic topic = (Topic) o; return Objects.equal(fqtn, topic.fqtn) && Objects.equal(topicName, topic.topicName) && Objects.equal(tnxEnabled, topic.tnxEnabled) && Objects.equal(owner, topic.owner); } @Override public int hashCode() { return Objects.hashCode(fqtn, topicName, tnxEnabled, owner); } }