/*
* Copyright © 2015-2016 Cask Data, Inc.
*
* 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.
*/
package co.cask.cdap.proto.element;
import co.cask.cdap.proto.Id;
import co.cask.cdap.proto.id.ApplicationId;
import co.cask.cdap.proto.id.ArtifactId;
import co.cask.cdap.proto.id.DatasetId;
import co.cask.cdap.proto.id.DatasetModuleId;
import co.cask.cdap.proto.id.DatasetTypeId;
import co.cask.cdap.proto.id.EntityId;
import co.cask.cdap.proto.id.FlowletId;
import co.cask.cdap.proto.id.FlowletQueueId;
import co.cask.cdap.proto.id.InstanceId;
import co.cask.cdap.proto.id.NamespaceId;
import co.cask.cdap.proto.id.NotificationFeedId;
import co.cask.cdap.proto.id.ProgramId;
import co.cask.cdap.proto.id.ProgramRunId;
import co.cask.cdap.proto.id.QueryId;
import co.cask.cdap.proto.id.ScheduleId;
import co.cask.cdap.proto.id.StreamId;
import co.cask.cdap.proto.id.StreamViewId;
import co.cask.cdap.proto.id.SystemServiceId;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Represents a type of CDAP element. E.g. namespace, application, datasets, streams.
*/
// TODO: remove duplication with EntityType in cdap-cli
@SuppressWarnings("unchecked")
public enum EntityType {
INSTANCE(InstanceId.class, null),
NAMESPACE(NamespaceId.class, Id.Namespace.class),
APPLICATION(ApplicationId.class, Id.Application.class),
PROGRAM(ProgramId.class, Id.Program.class),
PROGRAM_RUN(ProgramRunId.class, Id.Program.Run.class),
STREAM(StreamId.class, Id.Stream.class),
STREAM_VIEW(StreamViewId.class, Id.Stream.View.class),
DATASET_TYPE(DatasetTypeId.class, Id.DatasetType.class),
DATASET_MODULE(DatasetModuleId.class, Id.DatasetModule.class),
FLOWLET(FlowletId.class, Id.Flow.Flowlet.class),
FLOWLET_QUEUE(FlowletQueueId.class, Id.Flow.Flowlet.Queue.class),
SCHEDULE(ScheduleId.class, Id.Schedule.class),
NOTIFICATION_FEED(NotificationFeedId.class, Id.NotificationFeed.class),
ARTIFACT(ArtifactId.class, Id.Artifact.class),
DATASET(DatasetId.class, Id.DatasetInstance.class),
QUERY(QueryId.class, Id.QueryHandle.class),
SYSTEM_SERVICE(SystemServiceId.class, Id.SystemService.class);
private static final Map<Class<? extends EntityId>, EntityType> byIdClass;
private static final Map<Class<? extends Id>, EntityType> byOldIdClass;
static {
Map<Class<? extends EntityId>, EntityType> byIdClassMap = new LinkedHashMap<>();
Map<Class<? extends Id>, EntityType> byOldIdClassMap = new LinkedHashMap<>();
for (EntityType type : EntityType.values()) {
byIdClassMap.put(type.getIdClass(), type);
if (type.getOldIdClass() != null) {
byOldIdClassMap.put(type.getOldIdClass(), type);
}
}
byIdClass = Collections.unmodifiableMap(byIdClassMap);
byOldIdClass = Collections.unmodifiableMap(byOldIdClassMap);
}
private final Class<? extends EntityId> idClass;
@Nullable
private final Class<? extends Id> oldIdClass;
private final MethodHandle fromIdParts;
EntityType(Class<? extends EntityId> idClass, Class<? extends Id> oldIdClass) {
this.idClass = idClass;
this.oldIdClass = oldIdClass;
try {
this.fromIdParts = MethodHandles.lookup()
.findStatic(idClass, "fromIdParts", MethodType.methodType(idClass, Iterable.class));
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException("Failed to initialize EntityType", e);
}
}
public Class<? extends EntityId> getIdClass() {
return idClass;
}
@Nullable
public Class<? extends Id> getOldIdClass() {
return oldIdClass;
}
public static EntityType valueOfIdClass(Class<? extends EntityId> idClass) {
if (!byIdClass.containsKey(idClass)) {
throw new IllegalArgumentException("No EntityType registered for ID class: " + idClass.getName());
}
return byIdClass.get(idClass);
}
public static EntityType valueOfOldIdClass(Class<? extends Id> oldIdClass) {
if (!byOldIdClass.containsKey(oldIdClass)) {
throw new IllegalArgumentException("No EntityType registered for old ID class: " + oldIdClass.getName());
}
return byOldIdClass.get(oldIdClass);
}
public <T extends EntityId> T fromIdParts(Iterable<String> idParts) {
try {
return (T) fromIdParts.invoke(idParts);
} catch (RuntimeException t) {
throw t;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}