| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.cassandra.schema; |
| |
| import java.util.List; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| |
| import org.apache.cassandra.cql3.functions.UDAggregate; |
| import org.apache.cassandra.cql3.functions.UDFunction; |
| import org.apache.cassandra.db.marshal.UserType; |
| import org.apache.cassandra.schema.SchemaTransformation.SchemaTransformationResult; |
| |
| /** |
| * Registers schema change listeners and sends the notifications. The interface of this class just takes the high level |
| * keyspace metadata changes. It iterates over all keyspaces elements and distributes appropriate notifications about |
| * changes around those elements (tables, views, types, functions). |
| */ |
| public class SchemaChangeNotifier |
| { |
| private final List<SchemaChangeListener> changeListeners = new CopyOnWriteArrayList<>(); |
| |
| public void registerListener(SchemaChangeListener listener) |
| { |
| changeListeners.add(listener); |
| } |
| |
| @SuppressWarnings("unused") |
| public void unregisterListener(SchemaChangeListener listener) |
| { |
| changeListeners.remove(listener); |
| } |
| |
| public void notifyKeyspaceCreated(KeyspaceMetadata keyspace) |
| { |
| notifyCreateKeyspace(keyspace); |
| keyspace.types.forEach(this::notifyCreateType); |
| keyspace.tables.forEach(this::notifyCreateTable); |
| keyspace.views.forEach(this::notifyCreateView); |
| keyspace.functions.udfs().forEach(this::notifyCreateFunction); |
| keyspace.functions.udas().forEach(this::notifyCreateAggregate); |
| } |
| |
| public void notifyKeyspaceAltered(KeyspaceMetadata.KeyspaceDiff delta, boolean dropData) |
| { |
| // notify on everything dropped |
| delta.udas.dropped.forEach(uda -> notifyDropAggregate((UDAggregate) uda)); |
| delta.udfs.dropped.forEach(udf -> notifyDropFunction((UDFunction) udf)); |
| delta.views.dropped.forEach(view -> notifyDropView(view, dropData)); |
| delta.tables.dropped.forEach(metadata -> notifyDropTable(metadata, dropData)); |
| delta.types.dropped.forEach(this::notifyDropType); |
| |
| // notify on everything created |
| delta.types.created.forEach(this::notifyCreateType); |
| delta.tables.created.forEach(this::notifyCreateTable); |
| delta.views.created.forEach(this::notifyCreateView); |
| delta.udfs.created.forEach(udf -> notifyCreateFunction((UDFunction) udf)); |
| delta.udas.created.forEach(uda -> notifyCreateAggregate((UDAggregate) uda)); |
| |
| // notify on everything altered |
| if (!delta.before.params.equals(delta.after.params)) |
| notifyAlterKeyspace(delta.before, delta.after); |
| delta.types.altered.forEach(diff -> notifyAlterType(diff.before, diff.after)); |
| delta.tables.altered.forEach(diff -> notifyAlterTable(diff.before, diff.after)); |
| delta.views.altered.forEach(diff -> notifyAlterView(diff.before, diff.after)); |
| delta.udfs.altered.forEach(diff -> notifyAlterFunction(diff.before, diff.after)); |
| delta.udas.altered.forEach(diff -> notifyAlterAggregate(diff.before, diff.after)); |
| } |
| |
| public void notifyKeyspaceDropped(KeyspaceMetadata keyspace, boolean dropData) |
| { |
| keyspace.functions.udas().forEach(this::notifyDropAggregate); |
| keyspace.functions.udfs().forEach(this::notifyDropFunction); |
| keyspace.views.forEach(view -> notifyDropView(view, dropData)); |
| keyspace.tables.forEach(metadata -> notifyDropTable(metadata, dropData)); |
| keyspace.types.forEach(this::notifyDropType); |
| notifyDropKeyspace(keyspace, dropData); |
| } |
| |
| public void notifyPreChanges(SchemaTransformationResult transformationResult) |
| { |
| transformationResult.diff.altered.forEach(this::notifyPreAlterKeyspace); |
| } |
| |
| private void notifyPreAlterKeyspace(KeyspaceMetadata.KeyspaceDiff keyspaceDiff) |
| { |
| keyspaceDiff.tables.altered.forEach(this::notifyPreAlterTable); |
| keyspaceDiff.views.altered.forEach(this::notifyPreAlterView); |
| } |
| |
| private void notifyPreAlterTable(Diff.Altered<TableMetadata> altered) |
| { |
| changeListeners.forEach(l -> l.onPreAlterTable(altered.before, altered.after)); |
| } |
| |
| private void notifyPreAlterView(Diff.Altered<ViewMetadata> altered) |
| { |
| changeListeners.forEach(l -> l.onPreAlterView(altered.before, altered.after)); |
| } |
| |
| private void notifyCreateKeyspace(KeyspaceMetadata ksm) |
| { |
| changeListeners.forEach(l -> l.onCreateKeyspace(ksm)); |
| } |
| |
| private void notifyCreateTable(TableMetadata metadata) |
| { |
| changeListeners.forEach(l -> l.onCreateTable(metadata)); |
| } |
| |
| private void notifyCreateView(ViewMetadata view) |
| { |
| changeListeners.forEach(l -> l.onCreateView(view)); |
| } |
| |
| private void notifyCreateType(UserType ut) |
| { |
| changeListeners.forEach(l -> l.onCreateType(ut)); |
| } |
| |
| private void notifyCreateFunction(UDFunction udf) |
| { |
| changeListeners.forEach(l -> l.onCreateFunction(udf)); |
| } |
| |
| private void notifyCreateAggregate(UDAggregate udf) |
| { |
| changeListeners.forEach(l -> l.onCreateAggregate(udf)); |
| } |
| |
| private void notifyAlterKeyspace(KeyspaceMetadata before, KeyspaceMetadata after) |
| { |
| changeListeners.forEach(l -> l.onAlterKeyspace(before, after)); |
| } |
| |
| private void notifyAlterTable(TableMetadata before, TableMetadata after) |
| { |
| boolean changeAffectedPreparedStatements = before.changeAffectsPreparedStatements(after); |
| changeListeners.forEach(l -> l.onAlterTable(before, after, changeAffectedPreparedStatements)); |
| } |
| |
| private void notifyAlterView(ViewMetadata before, ViewMetadata after) |
| { |
| boolean changeAffectedPreparedStatements = before.metadata.changeAffectsPreparedStatements(after.metadata); |
| changeListeners.forEach(l -> l.onAlterView(before, after, changeAffectedPreparedStatements)); |
| } |
| |
| private void notifyAlterType(UserType before, UserType after) |
| { |
| changeListeners.forEach(l -> l.onAlterType(before, after)); |
| } |
| |
| private void notifyAlterFunction(UDFunction before, UDFunction after) |
| { |
| changeListeners.forEach(l -> l.onAlterFunction(before, after)); |
| } |
| |
| private void notifyAlterAggregate(UDAggregate before, UDAggregate after) |
| { |
| changeListeners.forEach(l -> l.onAlterAggregate(before, after)); |
| } |
| |
| private void notifyDropKeyspace(KeyspaceMetadata ksm, boolean dropData) |
| { |
| changeListeners.forEach(l -> l.onDropKeyspace(ksm, dropData)); |
| } |
| |
| private void notifyDropTable(TableMetadata metadata, boolean dropData) |
| { |
| changeListeners.forEach(l -> l.onDropTable(metadata, dropData)); |
| } |
| |
| private void notifyDropView(ViewMetadata view, boolean dropData) |
| { |
| changeListeners.forEach(l -> l.onDropView(view, dropData)); |
| } |
| |
| private void notifyDropType(UserType ut) |
| { |
| changeListeners.forEach(l -> l.onDropType(ut)); |
| } |
| |
| private void notifyDropFunction(UDFunction udf) |
| { |
| changeListeners.forEach(l -> l.onDropFunction(udf)); |
| } |
| |
| private void notifyDropAggregate(UDAggregate udf) |
| { |
| changeListeners.forEach(l -> l.onDropAggregate(udf)); |
| } |
| } |